In this script, simulate 5 different data sets. All will be 50
subjects, 50 taxa, with 0.90 connectance but then varying degrees of
covariate strength. Going to hold two covariate strengths constant and
then vary the sex differences
1. Load Library
library(tidyverse)
library(igraph)
library(NBZIMM)
library(SpiecEasi)
library(LIMON)
library(here)
library(lme4)
library(Matrix)
library(tscount)
library(patchwork)
library(MASS)
library(matrixcalc)
library(gridExtra)
library(devtools)
library(miaSim)
library(reshape2)
2. Simulate beta = 0.01
Simulate Counts
Simulate GLV for 50 individuals, 50 species, 10 timepoints, Connectance
= 0.90, Sex Beta = 0.01
# Set seed
set.seed(12345)
# Step 1 Run GLV for n number of subject and timepoints
###############################################################################
# Generate interactions from uniform distribution
A_uniform <- randomA(
n_species = 50,
diagonal = -1.0,
connectance = 0.90)
# Create an empty list to store the count tables for each subject
count_tables <- list()
# Loop through 50 subjects and generate count tables for each
for (i in 1:50) {
# Set the seed for each subject
set.seed(12345 + i)
# Generalized Lotka-Volterra (gLV)
tse_glv <- simulateGLV(n_species = 50,
A = A_uniform,
t_start = 0,
t_store = 10,
stochastic = FALSE,
norm = FALSE,
error_variance = 0.01)
# Get the count table
sim_data <- tse_glv@assays@data@listData[["counts"]]
# Store the count table in the list
count_tables[[i]] <- t(sim_data)
}
# Step 2 - Merge together
###############################################################################
# Combine all count tables into one data frame
combined_count_table <- do.call(rbind, count_tables)
# Rename the rownames based on the count table number
rownames(combined_count_table) <- paste0("Sbj", rep(1:50, each = nrow(count_tables[[1]])), "_Time", 1:10)
Create Fake Metadata
1. Sex (M or F, 50/50 Ratio) 2. Age - sample from between 18 and 45 3.
BMI - sample between 18 and 35
Make Metadata and merge with the count data
meta_data <- expand.grid(Time = 1:10,ID = 1:50)
rownames(meta_data) <- rownames(combined_count_table)
# Set seed
set.seed(12345)
meta_data$Sex <- rep(c(0, 1), each = 50)
# Set seed
set.seed(12345)
meta_data$Age <- rep(sample(18:45, 50, replace = TRUE), each = 10)
# Set seed
set.seed(12345)
meta_data$BMI <- rep(sample(18:35, 50, replace = TRUE), each = 10)
# Center the continuous variables
meta_data$Age <- meta_data$Age - mean(meta_data$Age)
meta_data$BMI <- meta_data$BMI - mean(meta_data$BMI)
# Df 2 is Metadata merged with Counts
########################################################
#Round off and increase
combined_count_table <- as.data.frame(combined_count_table + abs(min(combined_count_table)))
combined_count_table <- (combined_count_table)*10
meta_counts <- base::merge(meta_data, combined_count_table, by ="row.names", all = TRUE)
meta_counts <- column_to_rownames(meta_counts, "Row.names")
Add in biological covariates
# Set seed
set.seed(12345)
# Addin covariates
########################################################################################
# Set up new dataframe
Long_data_new <- meta_counts
# Loop running the LM to get new variables with error that has a range of values
# Taxa 21 - 30 will have Sex effect
for (i in 26:35) {
error <- rnorm(nrow(Long_data_new), mean = 1, sd = 0.6)
Long_data_new[, i] <- Long_data_new[, i] + 0.01 * Long_data_new$Sex + error
}
# round the counts to bring them back up to 0
########################################################################################
# Add the minimum value to bring everything up to at least 0
count_table1 <- Long_data_new[,6:55]
# scale to positive and make larger
count_table1 <- count_table1 + abs(min(count_table1))
count_table1 <- round(count_table1*10)
#change Long_data_new
Long_data_new[,6:55] <- count_table1
Now Add in 0s
# Set up new dataframe
predata_0 <- count_table1
# Add the 0s back in
########################################################################################
# Step 1: Calculate total counts for each column
total_counts <- colSums(predata_0)
# Step 2: Create probability gradient
gradient <- seq(0.5, 0.2, length.out = ncol(predata_0))
# Step 3: Make the probability gradient inverse to total counts (ie higher total value, lower proportion of 0s)
total_counts <- total_counts[order(total_counts)]
gradient <- gradient[order(-gradient)]
# Step 4 & 5: Generate random numbers and set counts to 0 based on probability gradient
for (i in seq_along(total_counts)) {
prob <- gradient[i]
# Calculate number of 0s to add based on probability
num_zeros <- sum(runif(nrow(predata_0)) <= prob)
# Randomly select rows to set to 0
# Set seed
set.seed(12345+i)
rows_to_zero <- sample(nrow(predata_0), num_zeros)
# Set counts to 0
predata_0[rows_to_zero, i] <- 0
}
# merge with metadata for plotting
zero_data1 <- merge(meta_data, predata_0, by = 0)
zero_data1 <- column_to_rownames(zero_data1, "Row.names")
#round the counts
zero_data1[,6:55] <- round(zero_data1[,6:55])
Graphs to Check
# Individual Species Plots
########################################################
# Pivot to long data
count_long <- tidyr::pivot_longer(zero_data1, cols = starts_with("sp"), names_to = "Species")
# Plot the data
count_long %>%
ggplot(aes(x = Time, y = value, colour = as.factor(ID),
group = as.factor(ID), linetype = as.factor(ID))) +
geom_line() +
geom_point() +
geom_jitter() +
ylab("Count") +
labs(linetype = "ID", color = "ID") +
facet_wrap(~ Species) + # Create a panel for each species
theme(legend.position = "none") +
ggtitle("Time Series of N=50, 0s")

# Distribution of counts
########################################################
hist(as.matrix(zero_data1[,6:55]), breaks = 100, main = "Distribution of GLV Data", xlab = "Counts")

# Correlation matrix
cor_raw1 <- cor((zero_data1[,6:55]), method = "spearman")
heatmap(cor_raw1, Colv = NA, Rowv = NA, main = "Correlation of 0 inflated no covariates")

Save the Counts
write.csv(meta_counts, here("Data","GLV_SimData", "Dataset_5","GLV_0.01.csv"))
write.csv(Long_data_new, here("Data","GLV_SimData", "Dataset_5","GLV_Cov_0.01.csv"))
write.csv(zero_data1, here("Data","GLV_SimData", "Dataset_5","GLV_CovZero_0.01.csv"))
3. Simulate beta = 0.10
Simulate Counts
Simulate GLV for 50 individuals, 50 species, 10 timepoints, Connectance
= 0.90, Sex Beta = 0.1
# Set seed
set.seed(12345)
# Step 1 Run GLV for n number of subject and timepoints
###############################################################################
# Generate interactions from uniform distribution
A_uniform <- randomA(
n_species = 50,
diagonal = -1.0,
connectance = 0.90)
# Create an empty list to store the count tables for each subject
count_tables <- list()
# Loop through 50 subjects and generate count tables for each
for (i in 1:50) {
# Set the seed for each subject
set.seed(12345 + i)
# Generalized Lotka-Volterra (gLV)
tse_glv <- simulateGLV(n_species = 50,
A = A_uniform,
t_start = 0,
t_store = 10,
stochastic = FALSE,
norm = FALSE,
error_variance = 0.01)
# Get the count table
sim_data <- tse_glv@assays@data@listData[["counts"]]
# Store the count table in the list
count_tables[[i]] <- t(sim_data)
}
# Step 2 - Merge together
###############################################################################
# Combine all count tables into one data frame
combined_count_table <- do.call(rbind, count_tables)
# Rename the rownames based on the count table number
rownames(combined_count_table) <- paste0("Sbj", rep(1:50, each = nrow(count_tables[[1]])), "_Time", 1:10)
Create Fake Metadata
1. Sex (M or F, 50/50 Ratio) 2. Age - sample from between 18 and 45 3.
BMI - sample between 18 and 35
Make Metadata and merge with the count data
# Df 1 is Metadata
########################################################
meta_data <- expand.grid(Time = 1:10,ID = 1:50)
rownames(meta_data) <- rownames(combined_count_table)
# Set seed
set.seed(12345)
meta_data$Sex <- rep(c(0, 1), each = 50)
# Set seed
set.seed(12345)
meta_data$Age <- rep(sample(18:45, 50, replace = TRUE), each = 10)
# Set seed
set.seed(12345)
meta_data$BMI <- rep(sample(18:35, 50, replace = TRUE), each = 10)
# Center the continuous variables
meta_data$Age <- meta_data$Age - mean(meta_data$Age)
meta_data$BMI <- meta_data$BMI - mean(meta_data$BMI)
# Df 2 is Metadata merged with Counts
########################################################
#Round off and increase
combined_count_table <- as.data.frame(combined_count_table + abs(min(combined_count_table)))
combined_count_table <- (combined_count_table)*10
meta_counts <- base::merge(meta_data, combined_count_table, by ="row.names", all = TRUE)
meta_counts <- column_to_rownames(meta_counts, "Row.names")
Add in biological covariates
# Set seed
set.seed(12345)
# Addin covariates
########################################################################################
# Set up new dataframe
Long_data_new <- meta_counts
# Loop running the LM to get new variables with error that has a range of values
# Taxa 21 - 30 will have Sex effect
for (i in 26:35) {
error <- rnorm(nrow(Long_data_new), mean = 1, sd = 0.6)
Long_data_new[, i] <- Long_data_new[, i] + 0.1 * Long_data_new$Sex + error
}
# round the counts to bring them back up to 0
########################################################################################
# Add the minimum value to bring everything up to at least 0
count_table1 <- Long_data_new[,6:55]
# scale to positive and make larger
count_table1 <- count_table1 + abs(min(count_table1))
count_table1 <- round(count_table1*10)
#change Long_data_new
Long_data_new[,6:55] <- count_table1
Now Add in 0s
# Set up new dataframe
predata_0 <- count_table1
# Add the 0s back in
########################################################################################
# Step 1: Calculate total counts for each column
total_counts <- colSums(predata_0)
# Step 2: Create probability gradient
gradient <- seq(0.5, 0.2, length.out = ncol(predata_0))
# Step 3: Make the probability gradient inverse to total counts (ie higher total value, lower proportion of 0s)
total_counts <- total_counts[order(total_counts)]
gradient <- gradient[order(-gradient)]
# Step 4 & 5: Generate random numbers and set counts to 0 based on probability gradient
for (i in seq_along(total_counts)) {
prob <- gradient[i]
# Calculate number of 0s to add based on probability
num_zeros <- sum(runif(nrow(predata_0)) <= prob)
# Randomly select rows to set to 0
# Set the seed for each subject
set.seed(12345 + i)
rows_to_zero <- sample(nrow(predata_0), num_zeros)
# Set counts to 0
predata_0[rows_to_zero, i] <- 0
}
# merge with metadata for plotting
zero_data1 <- merge(meta_data, predata_0, by = 0)
zero_data1 <- column_to_rownames(zero_data1, "Row.names")
#round the counts
zero_data1[,6:55] <- round(zero_data1[,6:55])
Graphs to Check
# Individual Species Plots
########################################################
# Pivot to long data
count_long <- tidyr::pivot_longer(zero_data1, cols = starts_with("sp"), names_to = "Species")
# Plot the data
count_long %>%
ggplot(aes(x = Time, y = value, colour = as.factor(ID),
group = as.factor(ID), linetype = as.factor(ID))) +
geom_line() +
geom_point() +
geom_jitter() +
ylab("Count") +
labs(linetype = "ID", color = "ID") +
facet_wrap(~ Species) + # Create a panel for each species
theme(legend.position = "none") +
ggtitle("Time Series of N=50, 0s")

# Distribution of counts
########################################################
hist(as.matrix(zero_data1[,6:55]), breaks = 100, main = "Distribution of GLV Data", xlab = "Counts")

# Correlation matrix
cor_raw1 <- cor((zero_data1[,6:55]), method = "spearman")
heatmap(cor_raw1, Colv = NA, Rowv = NA, main = "Correlation of 0 inflated no covariates")

Save the Counts
write.csv(meta_counts, here("Data","GLV_SimData", "Dataset_5","GLV_0.10.csv"))
write.csv(Long_data_new, here("Data","GLV_SimData", "Dataset_5","GLV_Cov_0.10.csv"))
write.csv(zero_data1, here("Data","GLV_SimData", "Dataset_5","GLV_CovZero_0.10.csv"))
4. Simulate beta = 1.0
Simulate Counts
Simulate GLV for 50 individuals, 50 species, 10 timepoints, Connectance
= 0.90, Sex Beta = 1.0
# Set seed
set.seed(12345)
# Step 1 Run GLV for n number of subject and timepoints
###############################################################################
# Generate interactions from uniform distribution
A_uniform <- randomA(
n_species = 50,
diagonal = -1.0,
connectance = 0.90)
# Create an empty list to store the count tables for each subject
count_tables <- list()
# Loop through 50 subjects and generate count tables for each
for (i in 1:50) {
# Set the seed for each subject
set.seed(12345 + i)
# Generalized Lotka-Volterra (gLV)
tse_glv <- simulateGLV(n_species = 50,
A = A_uniform,
t_start = 0,
t_store = 10,
stochastic = FALSE,
norm = FALSE,
error_variance = 0.01)
# Get the count table
sim_data <- tse_glv@assays@data@listData[["counts"]]
# Store the count table in the list
count_tables[[i]] <- t(sim_data)
}
# Step 2 - Merge together
###############################################################################
# Combine all count tables into one data frame
combined_count_table <- do.call(rbind, count_tables)
# Rename the rownames based on the count table number
rownames(combined_count_table) <- paste0("Sbj", rep(1:50, each = nrow(count_tables[[1]])), "_Time", 1:10)
Create Fake Metadata
1. Sex (M or F, 50/50 Ratio) 2. Age - sample from between 18 and 45 3.
BMI - sample between 18 and 35
Make Metadata and merge with the count data
# Df 1 is Metadata
########################################################
meta_data <- expand.grid(Time = 1:10,ID = 1:50)
rownames(meta_data) <- rownames(combined_count_table)
# Set seed
set.seed(12345)
meta_data$Sex <- rep(c(0, 1), each = 50)
# Set seed
set.seed(12345)
meta_data$Age <- rep(sample(18:45, 50, replace = TRUE), each = 10)
# Set seed
set.seed(12345)
meta_data$BMI <- rep(sample(18:35, 50, replace = TRUE), each = 10)
# Center the continuous variables
meta_data$Age <- meta_data$Age - mean(meta_data$Age)
meta_data$BMI <- meta_data$BMI - mean(meta_data$BMI)
# Df 2 is Metadata merged with Counts
########################################################
#Round off and increase
combined_count_table <- as.data.frame(combined_count_table + abs(min(combined_count_table)))
combined_count_table <- (combined_count_table)*10
meta_counts <- base::merge(meta_data, combined_count_table, by ="row.names", all = TRUE)
meta_counts <- column_to_rownames(meta_counts, "Row.names")
Add in biological covariates
# Set seed
set.seed(12345)
# Addin covariates
########################################################################################
# Set up new dataframe
Long_data_new <- meta_counts
# Loop running the LM to get new variables with error that has a range of values
# Taxa 21 - 30 will have Sex effect
for (i in 26:35) {
error <- rnorm(nrow(Long_data_new), mean = 1, sd = 0.6)
Long_data_new[, i] <- Long_data_new[, i] + 1.0 * Long_data_new$Sex + error
}
# round the counts to bring them back up to 0
########################################################################################
# Add the minimum value to bring everything up to at least 0
count_table1 <- Long_data_new[,6:55]
# scale to positive and make larger
count_table1 <- count_table1 + abs(min(count_table1))
count_table1 <- round(count_table1*10)
#change Long_data_new
Long_data_new[,6:55] <- count_table1
Now Add in 0s
# Set up new dataframe
predata_0 <- count_table1
# Add the 0s back in
########################################################################################
# Step 1: Calculate total counts for each column
total_counts <- colSums(predata_0)
# Step 2: Create probability gradient
gradient <- seq(0.5, 0.2, length.out = ncol(predata_0))
# Step 3: Make the probability gradient inverse to total counts (ie higher total value, lower proportion of 0s)
total_counts <- total_counts[order(total_counts)]
gradient <- gradient[order(-gradient)]
# Step 4 & 5: Generate random numbers and set counts to 0 based on probability gradient
for (i in seq_along(total_counts)) {
prob <- gradient[i]
# Calculate number of 0s to add based on probability
num_zeros <- sum(runif(nrow(predata_0)) <= prob)
# Randomly select rows to set to 0
# Set the seed for each subject
set.seed(12345 + i)
rows_to_zero <- sample(nrow(predata_0), num_zeros)
# Set counts to 0
predata_0[rows_to_zero, i] <- 0
}
# merge with metadata for plotting
zero_data1 <- merge(meta_data, predata_0, by = 0)
zero_data1 <- column_to_rownames(zero_data1, "Row.names")
#round the counts
zero_data1[,6:55] <- round(zero_data1[,6:55])
Graphs to Check
# Individual Species Plots
########################################################
# Pivot to long data
count_long <- tidyr::pivot_longer(zero_data1, cols = starts_with("sp"), names_to = "Species")
# Plot the data
count_long %>%
ggplot(aes(x = Time, y = value, colour = as.factor(ID),
group = as.factor(ID), linetype = as.factor(ID))) +
geom_line() +
geom_point() +
geom_jitter() +
ylab("Count") +
labs(linetype = "ID", color = "ID") +
facet_wrap(~ Species) + # Create a panel for each species
theme(legend.position = "none") +
ggtitle("Time Series of N=50, 0s")

# Distribution of counts
########################################################
hist(as.matrix(zero_data1[,6:55]), breaks = 100, main = "Distribution of GLV Data", xlab = "Counts")

# Correlation matrix
cor_raw1 <- cor((zero_data1[,6:55]), method = "spearman")
heatmap(cor_raw1, Colv = NA, Rowv = NA, main = "Correlation of 0 inflated no covariates")

Save the Counts
write.csv(meta_counts, here("Data","GLV_SimData", "Dataset_5","GLV_1.0.csv"))
write.csv(Long_data_new, here("Data","GLV_SimData", "Dataset_5","GLV_Cov_1.0.csv"))
write.csv(zero_data1, here("Data","GLV_SimData", "Dataset_5","GLV_CovZero_1.0.csv"))
5. Simulate beta = 8.0
Simulate Counts
Simulate GLV for 50 individuals, 50 species, 10 timepoints, Connectance
= 0.90, Sex Beta = 8.0
# Set seed
set.seed(12345)
# Step 1 Run GLV for n number of subject and timepoints
###############################################################################
# Generate interactions from uniform distribution
A_uniform <- randomA(
n_species = 50,
diagonal = -1.0,
connectance = 0.90)
# Create an empty list to store the count tables for each subject
count_tables <- list()
# Loop through 50 subjects and generate count tables for each
for (i in 1:50) {
# Set the seed for each subject
set.seed(12345 + i)
# Generalized Lotka-Volterra (gLV)
tse_glv <- simulateGLV(n_species = 50,
A = A_uniform,
t_start = 0,
t_store = 10,
stochastic = FALSE,
norm = FALSE,
error_variance = 0.01)
# Get the count table
sim_data <- tse_glv@assays@data@listData[["counts"]]
# Store the count table in the list
count_tables[[i]] <- t(sim_data)
}
# Step 2 - Merge together
###############################################################################
# Combine all count tables into one data frame
combined_count_table <- do.call(rbind, count_tables)
# Rename the rownames based on the count table number
rownames(combined_count_table) <- paste0("Sbj", rep(1:50, each = nrow(count_tables[[1]])), "_Time", 1:10)
Create Fake Metadata
1. Sex (M or F, 50/50 Ratio) 2. Age - sample from between 18 and 45 3.
BMI - sample between 18 and 35
Make Metadata and merge with the count data
# Df 1 is Metadata
########################################################
meta_data <- expand.grid(Time = 1:10,ID = 1:50)
rownames(meta_data) <- rownames(combined_count_table)
# Set seed
set.seed(12345)
meta_data$Sex <- rep(c(0, 1), each = 50)
# Set seed
set.seed(12345)
meta_data$Age <- rep(sample(18:45, 50, replace = TRUE), each = 10)
# Set seed
set.seed(12345)
meta_data$BMI <- rep(sample(18:35, 50, replace = TRUE), each = 10)
# Center the continuous variables
meta_data$Age <- meta_data$Age - mean(meta_data$Age)
meta_data$BMI <- meta_data$BMI - mean(meta_data$BMI)
# Df 2 is Metadata merged with Counts
########################################################
#Round off and increase
combined_count_table <- as.data.frame(combined_count_table + abs(min(combined_count_table)))
combined_count_table <- (combined_count_table)*10
meta_counts <- base::merge(meta_data, combined_count_table, by ="row.names", all = TRUE)
meta_counts <- column_to_rownames(meta_counts, "Row.names")
Add in biological covariates
# Set seed
set.seed(12345)
# Addin covariates
########################################################################################
# Set up new dataframe
Long_data_new <- meta_counts
# Loop running the LM to get new variables with error that has a range of values
# Taxa 21 - 30 will have Sex effect
for (i in 26:35) {
error <- rnorm(nrow(Long_data_new), mean = 1, sd = 0.6)
Long_data_new[, i] <- Long_data_new[, i] + 8.0 * Long_data_new$Sex + error
}
# round the counts to bring them back up to 0
########################################################################################
# Add the minimum value to bring everything up to at least 0
count_table1 <- Long_data_new[,6:55]
# scale to positive and make larger
count_table1 <- count_table1 + abs(min(count_table1))
count_table1 <- round(count_table1*10)
#change Long_data_new
Long_data_new[,6:55] <- count_table1
Now Add in 0s
# Set up new dataframe
predata_0 <- count_table1
# Add the 0s back in
########################################################################################
# Step 1: Calculate total counts for each column
total_counts <- colSums(predata_0)
# Step 2: Create probability gradient
gradient <- seq(0.5, 0.2, length.out = ncol(predata_0))
# Step 3: Make the probability gradient inverse to total counts (ie higher total value, lower proportion of 0s)
total_counts <- total_counts[order(total_counts)]
gradient <- gradient[order(-gradient)]
# Step 4 & 5: Generate random numbers and set counts to 0 based on probability gradient
for (i in seq_along(total_counts)) {
prob <- gradient[i]
# Calculate number of 0s to add based on probability
num_zeros <- sum(runif(nrow(predata_0)) <= prob)
# Randomly select rows to set to 0
# Set the seed for each subject
set.seed(12345 + i)
rows_to_zero <- sample(nrow(predata_0), num_zeros)
# Set counts to 0
predata_0[rows_to_zero, i] <- 0
}
# merge with metadata for plotting
zero_data1 <- merge(meta_data, predata_0, by = 0)
zero_data1 <- column_to_rownames(zero_data1, "Row.names")
#round the counts
zero_data1[,6:55] <- round(zero_data1[,6:55])
Graphs to Check
# Individual Species Plots
########################################################
# Pivot to long data
count_long <- tidyr::pivot_longer(zero_data1, cols = starts_with("sp"), names_to = "Species")
# Plot the data
count_long %>%
ggplot(aes(x = Time, y = value, colour = as.factor(ID),
group = as.factor(ID), linetype = as.factor(ID))) +
geom_line() +
geom_point() +
geom_jitter() +
ylab("Count") +
labs(linetype = "ID", color = "ID") +
facet_wrap(~ Species) + # Create a panel for each species
theme(legend.position = "none") +
ggtitle("Time Series of N=50, 0s")

# Distribution of counts
########################################################
hist(as.matrix(zero_data1[,6:55]), breaks = 100, main = "Distribution of GLV Data", xlab = "Counts")

# Correlation matrix
cor_raw1 <- cor((zero_data1[,6:55]), method = "spearman")
heatmap(cor_raw1, Colv = NA, Rowv = NA, main = "Correlation of 0 inflated no covariates")

Save the Counts
write.csv(meta_counts, here("Data","GLV_SimData", "Dataset_5","GLV_8.0.csv"))
write.csv(Long_data_new, here("Data","GLV_SimData", "Dataset_5","GLV_Cov_8.0.csv"))
write.csv(zero_data1, here("Data","GLV_SimData", "Dataset_5","GLV_CovZero_8.0.csv"))
6. Simulate beta = 15.0
Simulate Counts
Simulate GLV for 50 individuals, 50 species, 10 timepoints, Connectance
= 0.90, Sex Beta = 15.0
# Set seed
set.seed(12345)
# Step 1 Run GLV for n number of subject and timepoints
###############################################################################
# Generate interactions from uniform distribution
A_uniform <- randomA(
n_species = 50,
diagonal = -1.0,
connectance = 0.90)
# Create an empty list to store the count tables for each subject
count_tables <- list()
# Loop through 50 subjects and generate count tables for each
for (i in 1:50) {
# Set the seed for each subject
set.seed(12345 + i)
# Generalized Lotka-Volterra (gLV)
tse_glv <- simulateGLV(n_species = 50,
A = A_uniform,
t_start = 0,
t_store = 10,
stochastic = FALSE,
norm = FALSE,
error_variance = 0.01)
# Get the count table
sim_data <- tse_glv@assays@data@listData[["counts"]]
# Store the count table in the list
count_tables[[i]] <- t(sim_data)
}
# Step 2 - Merge together
###############################################################################
# Combine all count tables into one data frame
combined_count_table <- do.call(rbind, count_tables)
# Rename the rownames based on the count table number
rownames(combined_count_table) <- paste0("Sbj", rep(1:50, each = nrow(count_tables[[1]])), "_Time", 1:10)
Create Fake Metadata
1. Sex (M or F, 50/50 Ratio) 2. Age - sample from between 18 and 45 3.
BMI - sample between 18 and 35
Make Metadata and merge with the count data
# Df 1 is Metadata
########################################################
meta_data <- expand.grid(Time = 1:10,ID = 1:50)
rownames(meta_data) <- rownames(combined_count_table)
# Set seed
set.seed(12345)
meta_data$Sex <- rep(c(0, 1), each = 50)
# Set seed
set.seed(12345)
meta_data$Age <- rep(sample(18:45, 50, replace = TRUE), each = 10)
# Set seed
set.seed(12345)
meta_data$BMI <- rep(sample(18:35, 50, replace = TRUE), each = 10)
# Center the continuous variables
meta_data$Age <- meta_data$Age - mean(meta_data$Age)
meta_data$BMI <- meta_data$BMI - mean(meta_data$BMI)
# Df 2 is Metadata merged with Counts
########################################################
#Round off and increase
combined_count_table <- as.data.frame(combined_count_table + abs(min(combined_count_table)))
combined_count_table <- (combined_count_table)*10
meta_counts <- base::merge(meta_data, combined_count_table, by ="row.names", all = TRUE)
meta_counts <- column_to_rownames(meta_counts, "Row.names")
Add in biological covariates
# Set seed
set.seed(12345)
# Addin covariates
########################################################################################
# Set up new dataframe
Long_data_new <- meta_counts
# Loop running the LM to get new variables with error that has a range of values
# Taxa 21 - 30 will have Sex effect
for (i in 26:35) {
error <- rnorm(nrow(Long_data_new), mean = 1, sd = 0.6)
Long_data_new[, i] <- Long_data_new[, i] + 15 * Long_data_new$Sex + error
}
# round the counts to bring them back up to 0
########################################################################################
# Add the minimum value to bring everything up to at least 0
count_table1 <- Long_data_new[,6:55]
# scale to positive and make larger
count_table1 <- count_table1 + abs(min(count_table1))
count_table1 <- round(count_table1*10)
#change Long_data_new
Long_data_new[,6:55] <- count_table1
Now Add in 0s
# Set up new dataframe
predata_0 <- count_table1
# Add the 0s back in
########################################################################################
# Step 1: Calculate total counts for each column
total_counts <- colSums(predata_0)
# Step 2: Create probability gradient
gradient <- seq(0.5, 0.2, length.out = ncol(predata_0))
# Step 3: Make the probability gradient inverse to total counts (ie higher total value, lower proportion of 0s)
total_counts <- total_counts[order(total_counts)]
gradient <- gradient[order(-gradient)]
# Step 4 & 5: Generate random numbers and set counts to 0 based on probability gradient
for (i in seq_along(total_counts)) {
prob <- gradient[i]
# Calculate number of 0s to add based on probability
num_zeros <- sum(runif(nrow(predata_0)) <= prob)
# Randomly select rows to set to 0
# Set the seed for each subject
set.seed(12345 + i)
rows_to_zero <- sample(nrow(predata_0), num_zeros)
# Set counts to 0
predata_0[rows_to_zero, i] <- 0
}
# merge with metadata for plotting
zero_data1 <- merge(meta_data, predata_0, by = 0)
zero_data1 <- column_to_rownames(zero_data1, "Row.names")
#round the counts
zero_data1[,6:55] <- round(zero_data1[,6:55])
Graphs to Check
# Individual Species Plots
########################################################
# Pivot to long data
count_long <- tidyr::pivot_longer(zero_data1, cols = starts_with("sp"), names_to = "Species")
# Plot the data
count_long %>%
ggplot(aes(x = Time, y = value, colour = as.factor(ID),
group = as.factor(ID), linetype = as.factor(ID))) +
geom_line() +
geom_point() +
geom_jitter() +
ylab("Count") +
labs(linetype = "ID", color = "ID") +
facet_wrap(~ Species) + # Create a panel for each species
theme(legend.position = "none") +
ggtitle("Time Series of N=50, 0s")

# Distribution of counts
########################################################
hist(as.matrix(zero_data1[,6:55]), breaks = 100, main = "Distribution of GLV Data", xlab = "Counts")

# Correlation matrix
cor_raw1 <- cor((zero_data1[,6:55]), method = "spearman")
heatmap(cor_raw1, Colv = NA, Rowv = NA, main = "Correlation of 0 inflated no covariates")

Save the Counts
write.csv(meta_counts, here("Data","GLV_SimData", "Dataset_5","GLV_15.0.csv"))
write.csv(Long_data_new, here("Data","GLV_SimData", "Dataset_5","GLV_Cov_15.0.csv"))
write.csv(zero_data1, here("Data","GLV_SimData", "Dataset_5","GLV_CovZero_15.0.csv"))
LS0tCnRpdGxlOiAiRGF0YSBTaW11bGF0aW9uIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpJbiB0aGlzIHNjcmlwdCwgc2ltdWxhdGUgNSBkaWZmZXJlbnQgZGF0YSBzZXRzLiBBbGwgd2lsbCBiZSA1MCBzdWJqZWN0cywgNTAgdGF4YSwgd2l0aCAwLjkwIGNvbm5lY3RhbmNlIGJ1dCB0aGVuIHZhcnlpbmcgZGVncmVlcyBvZiBjb3ZhcmlhdGUgc3RyZW5ndGguIEdvaW5nIHRvIGhvbGQgdHdvIGNvdmFyaWF0ZSBzdHJlbmd0aHMgY29uc3RhbnQgYW5kIHRoZW4gdmFyeSB0aGUgc2V4IGRpZmZlcmVuY2VzCgojIDEuIExvYWQgTGlicmFyeQoqKiogCgoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGlncmFwaCkKbGlicmFyeShOQlpJTU0pCmxpYnJhcnkoU3BpZWNFYXNpKQpsaWJyYXJ5KExJTU9OKQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkobG1lNCkKbGlicmFyeShNYXRyaXgpCmxpYnJhcnkodHNjb3VudCkKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoTUFTUykKbGlicmFyeShtYXRyaXhjYWxjKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShkZXZ0b29scykKbGlicmFyeShtaWFTaW0pCmxpYnJhcnkocmVzaGFwZTIpCmBgYAoKCgojIDIuIFNpbXVsYXRlIGJldGEgPSAwLjAxCioqKiAKCl9fU2ltdWxhdGUgQ291bnRzX18gIApTaW11bGF0ZSBHTFYgZm9yIDUwIGluZGl2aWR1YWxzLCA1MCBzcGVjaWVzLCAxMCB0aW1lcG9pbnRzLCBDb25uZWN0YW5jZSA9IDAuOTAsIFNleCBCZXRhID0gMC4wMQpgYGB7cn0KIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKCiMgU3RlcCAxIFJ1biBHTFYgZm9yIG4gbnVtYmVyIG9mIHN1YmplY3QgYW5kIHRpbWVwb2ludHMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBHZW5lcmF0ZSBpbnRlcmFjdGlvbnMgZnJvbSB1bmlmb3JtIGRpc3RyaWJ1dGlvbgpBX3VuaWZvcm0gPC0gcmFuZG9tQSgKICAgIG5fc3BlY2llcyA9IDUwLAogICAgZGlhZ29uYWwgPSAtMS4wLAogICAgY29ubmVjdGFuY2UgPSAwLjkwKQoKIyBDcmVhdGUgYW4gZW1wdHkgbGlzdCB0byBzdG9yZSB0aGUgY291bnQgdGFibGVzIGZvciBlYWNoIHN1YmplY3QKY291bnRfdGFibGVzIDwtIGxpc3QoKQoKCiMgTG9vcCB0aHJvdWdoIDUwIHN1YmplY3RzIGFuZCBnZW5lcmF0ZSBjb3VudCB0YWJsZXMgZm9yIGVhY2gKZm9yIChpIGluIDE6NTApIHsKICAjIFNldCB0aGUgc2VlZCBmb3IgZWFjaCBzdWJqZWN0CiAgc2V0LnNlZWQoMTIzNDUgKyBpKSAgCiAjIEdlbmVyYWxpemVkIExvdGthLVZvbHRlcnJhIChnTFYpCiAgdHNlX2dsdiA8LSBzaW11bGF0ZUdMVihuX3NwZWNpZXMgPSA1MCwKICAgICAgICAgICAgICAgICAgICAgICBBID0gQV91bmlmb3JtLAogICAgICAgICAgICAgICAgICAgICAgIHRfc3RhcnQgPSAwLCAKICAgICAgICAgICAgICAgICAgICAgICB0X3N0b3JlID0gMTAsCiAgICAgICAgICAgICAgICAgICAgICAgc3RvY2hhc3RpYyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIG5vcm0gPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBlcnJvcl92YXJpYW5jZSA9IDAuMDEpCiAgCiAgIyBHZXQgdGhlIGNvdW50IHRhYmxlCiAgc2ltX2RhdGEgPC0gdHNlX2dsdkBhc3NheXNAZGF0YUBsaXN0RGF0YVtbImNvdW50cyJdXQogIAogICMgU3RvcmUgdGhlIGNvdW50IHRhYmxlIGluIHRoZSBsaXN0CiAgY291bnRfdGFibGVzW1tpXV0gPC0gdChzaW1fZGF0YSkKfQoKIyBTdGVwIDIgLSBNZXJnZSB0b2dldGhlcgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgQ29tYmluZSBhbGwgY291bnQgdGFibGVzIGludG8gb25lIGRhdGEgZnJhbWUKY29tYmluZWRfY291bnRfdGFibGUgPC0gZG8uY2FsbChyYmluZCwgY291bnRfdGFibGVzKQoKIyBSZW5hbWUgdGhlIHJvd25hbWVzIGJhc2VkIG9uIHRoZSBjb3VudCB0YWJsZSBudW1iZXIKcm93bmFtZXMoY29tYmluZWRfY291bnRfdGFibGUpIDwtIHBhc3RlMCgiU2JqIiwgcmVwKDE6NTAsIGVhY2ggPSBucm93KGNvdW50X3RhYmxlc1tbMV1dKSksICJfVGltZSIsIDE6MTApCgpgYGAKCgpfX0NyZWF0ZSBGYWtlIE1ldGFkYXRhX18gIAoxLiBTZXggKE0gb3IgRiwgNTAvNTAgUmF0aW8pCjIuIEFnZSAtIHNhbXBsZSBmcm9tIGJldHdlZW4gMTggYW5kIDQ1CjMuIEJNSSAtIHNhbXBsZSBiZXR3ZWVuIDE4IGFuZCAzNQoKTWFrZSBNZXRhZGF0YSBhbmQgbWVyZ2Ugd2l0aCB0aGUgY291bnQgZGF0YQpgYGB7cn0KbWV0YV9kYXRhIDwtICBleHBhbmQuZ3JpZChUaW1lID0gMToxMCxJRCA9IDE6NTApCnJvd25hbWVzKG1ldGFfZGF0YSkgPC0gcm93bmFtZXMoY29tYmluZWRfY291bnRfdGFibGUpCiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCm1ldGFfZGF0YSRTZXggPC0gcmVwKGMoMCwgMSksIGVhY2ggPSA1MCkKIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKbWV0YV9kYXRhJEFnZSA8LSByZXAoc2FtcGxlKDE4OjQ1LCA1MCwgcmVwbGFjZSA9IFRSVUUpLCBlYWNoID0gMTApCiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCm1ldGFfZGF0YSRCTUkgPC0gcmVwKHNhbXBsZSgxODozNSwgNTAsIHJlcGxhY2UgPSBUUlVFKSwgZWFjaCA9IDEwKQoKIyBDZW50ZXIgdGhlIGNvbnRpbnVvdXMgdmFyaWFibGVzCm1ldGFfZGF0YSRBZ2UgPC0gbWV0YV9kYXRhJEFnZSAtIG1lYW4obWV0YV9kYXRhJEFnZSkKbWV0YV9kYXRhJEJNSSA8LSBtZXRhX2RhdGEkQk1JIC0gbWVhbihtZXRhX2RhdGEkQk1JKQoKCiMgRGYgMiBpcyBNZXRhZGF0YSBtZXJnZWQgd2l0aCBDb3VudHMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKI1JvdW5kIG9mZiBhbmQgaW5jcmVhc2UKY29tYmluZWRfY291bnRfdGFibGUgPC0gYXMuZGF0YS5mcmFtZShjb21iaW5lZF9jb3VudF90YWJsZSArIGFicyhtaW4oY29tYmluZWRfY291bnRfdGFibGUpKSkKY29tYmluZWRfY291bnRfdGFibGUgPC0gKGNvbWJpbmVkX2NvdW50X3RhYmxlKSoxMAptZXRhX2NvdW50cyA8LSBiYXNlOjptZXJnZShtZXRhX2RhdGEsIGNvbWJpbmVkX2NvdW50X3RhYmxlLCBieSA9InJvdy5uYW1lcyIsIGFsbCA9IFRSVUUpCm1ldGFfY291bnRzIDwtIGNvbHVtbl90b19yb3duYW1lcyhtZXRhX2NvdW50cywgIlJvdy5uYW1lcyIpCgoKYGBgCgoKQWRkIGluIGJpb2xvZ2ljYWwgY292YXJpYXRlcwpgYGB7cn0KIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKIyBBZGRpbiBjb3ZhcmlhdGVzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBTZXQgdXAgbmV3IGRhdGFmcmFtZQpMb25nX2RhdGFfbmV3IDwtIG1ldGFfY291bnRzCgoKIyBMb29wIHJ1bm5pbmcgdGhlIExNIHRvIGdldCBuZXcgdmFyaWFibGVzIHdpdGggZXJyb3IgdGhhdCBoYXMgYSByYW5nZSBvZiB2YWx1ZXMKIyBUYXhhIDIxIC0gMzAgd2lsbCBoYXZlIFNleCBlZmZlY3QKZm9yIChpIGluIDI2OjM1KSB7CiAgZXJyb3IgPC0gcm5vcm0obnJvdyhMb25nX2RhdGFfbmV3KSwgbWVhbiA9IDEsIHNkID0gMC42KQogIExvbmdfZGF0YV9uZXdbLCBpXSA8LSBMb25nX2RhdGFfbmV3WywgaV0gKyAwLjAxICogTG9uZ19kYXRhX25ldyRTZXggKyBlcnJvcgp9CgojIHJvdW5kIHRoZSBjb3VudHMgdG8gYnJpbmcgdGhlbSBiYWNrIHVwIHRvIDAKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBBZGQgdGhlIG1pbmltdW0gdmFsdWUgdG8gYnJpbmcgZXZlcnl0aGluZyB1cCB0byBhdCBsZWFzdCAwCmNvdW50X3RhYmxlMSA8LSBMb25nX2RhdGFfbmV3Wyw2OjU1XQoKCiMgc2NhbGUgdG8gcG9zaXRpdmUgYW5kIG1ha2UgbGFyZ2VyCmNvdW50X3RhYmxlMSA8LSBjb3VudF90YWJsZTEgKyBhYnMobWluKGNvdW50X3RhYmxlMSkpCmNvdW50X3RhYmxlMSA8LSByb3VuZChjb3VudF90YWJsZTEqMTApCgojY2hhbmdlIExvbmdfZGF0YV9uZXcKTG9uZ19kYXRhX25ld1ssNjo1NV0gPC0gY291bnRfdGFibGUxCmBgYAoKCgpOb3cgQWRkIGluIDBzCmBgYHtyfQojIFNldCB1cCBuZXcgZGF0YWZyYW1lCnByZWRhdGFfMCA8LSBjb3VudF90YWJsZTEKCiMgQWRkIHRoZSAwcyBiYWNrIGluCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCgojIFN0ZXAgMTogQ2FsY3VsYXRlIHRvdGFsIGNvdW50cyBmb3IgZWFjaCBjb2x1bW4KdG90YWxfY291bnRzIDwtIGNvbFN1bXMocHJlZGF0YV8wKQoKCiMgU3RlcCAyOiBDcmVhdGUgcHJvYmFiaWxpdHkgZ3JhZGllbnQKZ3JhZGllbnQgPC0gc2VxKDAuNSwgMC4yLCBsZW5ndGgub3V0ID0gbmNvbChwcmVkYXRhXzApKQoKIyBTdGVwIDM6IE1ha2UgdGhlIHByb2JhYmlsaXR5IGdyYWRpZW50IGludmVyc2UgdG8gdG90YWwgY291bnRzIChpZSBoaWdoZXIgdG90YWwgdmFsdWUsIGxvd2VyIHByb3BvcnRpb24gb2YgMHMpCnRvdGFsX2NvdW50cyA8LSB0b3RhbF9jb3VudHNbb3JkZXIodG90YWxfY291bnRzKV0KZ3JhZGllbnQgPC0gZ3JhZGllbnRbb3JkZXIoLWdyYWRpZW50KV0KCiMgU3RlcCA0ICYgNTogR2VuZXJhdGUgcmFuZG9tIG51bWJlcnMgYW5kIHNldCBjb3VudHMgdG8gMCBiYXNlZCBvbiBwcm9iYWJpbGl0eSBncmFkaWVudAoKZm9yIChpIGluIHNlcV9hbG9uZyh0b3RhbF9jb3VudHMpKSB7CiAgcHJvYiA8LSBncmFkaWVudFtpXQogICMgQ2FsY3VsYXRlIG51bWJlciBvZiAwcyB0byBhZGQgYmFzZWQgb24gcHJvYmFiaWxpdHkKICBudW1femVyb3MgPC0gc3VtKHJ1bmlmKG5yb3cocHJlZGF0YV8wKSkgPD0gcHJvYikKICAjIFJhbmRvbWx5IHNlbGVjdCByb3dzIHRvIHNldCB0byAwCiAgIyBTZXQgc2VlZAogIHNldC5zZWVkKDEyMzQ1K2kpCiAgcm93c190b196ZXJvIDwtIHNhbXBsZShucm93KHByZWRhdGFfMCksIG51bV96ZXJvcykKICAjIFNldCBjb3VudHMgdG8gMAogIHByZWRhdGFfMFtyb3dzX3RvX3plcm8sIGldIDwtIDAKfQoKIyBtZXJnZSB3aXRoIG1ldGFkYXRhIGZvciBwbG90dGluZwp6ZXJvX2RhdGExIDwtIG1lcmdlKG1ldGFfZGF0YSwgcHJlZGF0YV8wLCBieSA9IDApCnplcm9fZGF0YTEgPC0gY29sdW1uX3RvX3Jvd25hbWVzKHplcm9fZGF0YTEsICJSb3cubmFtZXMiKQojcm91bmQgdGhlIGNvdW50cwp6ZXJvX2RhdGExWyw2OjU1XSA8LSByb3VuZCh6ZXJvX2RhdGExWyw2OjU1XSkKYGBgCgpHcmFwaHMgdG8gQ2hlY2sKYGBge3J9CiMgSW5kaXZpZHVhbCBTcGVjaWVzIFBsb3RzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgUGl2b3QgdG8gbG9uZyBkYXRhCmNvdW50X2xvbmcgPC0gdGlkeXI6OnBpdm90X2xvbmdlcih6ZXJvX2RhdGExLCBjb2xzID0gc3RhcnRzX3dpdGgoInNwIiksIG5hbWVzX3RvID0gIlNwZWNpZXMiKQoKIyBQbG90IHRoZSBkYXRhCmNvdW50X2xvbmcgJT4lCiAgZ2dwbG90KGFlcyh4ID0gVGltZSwgeSA9IHZhbHVlLCBjb2xvdXIgPSBhcy5mYWN0b3IoSUQpLAogICAgICAgICAgICAgZ3JvdXAgPSBhcy5mYWN0b3IoSUQpLCBsaW5ldHlwZSA9IGFzLmZhY3RvcihJRCkpKSArCiAgZ2VvbV9saW5lKCkgKyAKICBnZW9tX3BvaW50KCkgKwogIGdlb21faml0dGVyKCkgKwogIHlsYWIoIkNvdW50IikgKwogIGxhYnMobGluZXR5cGUgPSAiSUQiLCBjb2xvciA9ICJJRCIpICsKICBmYWNldF93cmFwKH4gU3BlY2llcykgKyAgIyBDcmVhdGUgYSBwYW5lbCBmb3IgZWFjaCBzcGVjaWVzCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgZ2d0aXRsZSgiVGltZSBTZXJpZXMgb2YgTj01MCwgMHMiKQoKCiMgRGlzdHJpYnV0aW9uIG9mIGNvdW50cwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpoaXN0KGFzLm1hdHJpeCh6ZXJvX2RhdGExWyw2OjU1XSksIGJyZWFrcyA9IDEwMCwgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgR0xWIERhdGEiLCB4bGFiID0gIkNvdW50cyIpCgojIENvcnJlbGF0aW9uIG1hdHJpeApjb3JfcmF3MSA8LSBjb3IoKHplcm9fZGF0YTFbLDY6NTVdKSwgbWV0aG9kID0gInNwZWFybWFuIikKaGVhdG1hcChjb3JfcmF3MSwgQ29sdiA9IE5BLCBSb3d2ID0gTkEsIG1haW4gPSAiQ29ycmVsYXRpb24gb2YgMCBpbmZsYXRlZCBubyBjb3ZhcmlhdGVzIikKYGBgCgoKU2F2ZSB0aGUgQ291bnRzCmBgYHtyfQp3cml0ZS5jc3YobWV0YV9jb3VudHMsIGhlcmUoIkRhdGEiLCJHTFZfU2ltRGF0YSIsICJEYXRhc2V0XzUiLCJHTFZfMC4wMS5jc3YiKSkKd3JpdGUuY3N2KExvbmdfZGF0YV9uZXcsIGhlcmUoIkRhdGEiLCJHTFZfU2ltRGF0YSIsICJEYXRhc2V0XzUiLCJHTFZfQ292XzAuMDEuY3N2IikpCndyaXRlLmNzdih6ZXJvX2RhdGExLCBoZXJlKCJEYXRhIiwiR0xWX1NpbURhdGEiLCAiRGF0YXNldF81IiwiR0xWX0Nvdlplcm9fMC4wMS5jc3YiKSkKYGBgCgoKCiMgMy4gU2ltdWxhdGUgYmV0YSA9IDAuMTAKKioqIAoKX19TaW11bGF0ZSBDb3VudHNfXyAgClNpbXVsYXRlIEdMViBmb3IgNTAgaW5kaXZpZHVhbHMsIDUwIHNwZWNpZXMsIDEwIHRpbWVwb2ludHMsIENvbm5lY3RhbmNlID0gMC45MCwgU2V4IEJldGEgPSAwLjEKYGBge3J9CiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCgojIFN0ZXAgMSBSdW4gR0xWIGZvciBuIG51bWJlciBvZiBzdWJqZWN0IGFuZCB0aW1lcG9pbnRzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgR2VuZXJhdGUgaW50ZXJhY3Rpb25zIGZyb20gdW5pZm9ybSBkaXN0cmlidXRpb24KQV91bmlmb3JtIDwtIHJhbmRvbUEoCiAgICBuX3NwZWNpZXMgPSA1MCwKICAgIGRpYWdvbmFsID0gLTEuMCwKICAgIGNvbm5lY3RhbmNlID0gMC45MCkKCiMgQ3JlYXRlIGFuIGVtcHR5IGxpc3QgdG8gc3RvcmUgdGhlIGNvdW50IHRhYmxlcyBmb3IgZWFjaCBzdWJqZWN0CmNvdW50X3RhYmxlcyA8LSBsaXN0KCkKCgojIExvb3AgdGhyb3VnaCA1MCBzdWJqZWN0cyBhbmQgZ2VuZXJhdGUgY291bnQgdGFibGVzIGZvciBlYWNoCmZvciAoaSBpbiAxOjUwKSB7CiAgIyBTZXQgdGhlIHNlZWQgZm9yIGVhY2ggc3ViamVjdAogIHNldC5zZWVkKDEyMzQ1ICsgaSkgIAogIyBHZW5lcmFsaXplZCBMb3RrYS1Wb2x0ZXJyYSAoZ0xWKQogIHRzZV9nbHYgPC0gc2ltdWxhdGVHTFYobl9zcGVjaWVzID0gNTAsCiAgICAgICAgICAgICAgICAgICAgICAgQSA9IEFfdW5pZm9ybSwKICAgICAgICAgICAgICAgICAgICAgICB0X3N0YXJ0ID0gMCwgCiAgICAgICAgICAgICAgICAgICAgICAgdF9zdG9yZSA9IDEwLAogICAgICAgICAgICAgICAgICAgICAgIHN0b2NoYXN0aWMgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBub3JtID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JfdmFyaWFuY2UgPSAwLjAxKQogIAogICMgR2V0IHRoZSBjb3VudCB0YWJsZQogIHNpbV9kYXRhIDwtIHRzZV9nbHZAYXNzYXlzQGRhdGFAbGlzdERhdGFbWyJjb3VudHMiXV0KICAKICAjIFN0b3JlIHRoZSBjb3VudCB0YWJsZSBpbiB0aGUgbGlzdAogIGNvdW50X3RhYmxlc1tbaV1dIDwtIHQoc2ltX2RhdGEpCn0KCiMgU3RlcCAyIC0gTWVyZ2UgdG9nZXRoZXIKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIENvbWJpbmUgYWxsIGNvdW50IHRhYmxlcyBpbnRvIG9uZSBkYXRhIGZyYW1lCmNvbWJpbmVkX2NvdW50X3RhYmxlIDwtIGRvLmNhbGwocmJpbmQsIGNvdW50X3RhYmxlcykKCiMgUmVuYW1lIHRoZSByb3duYW1lcyBiYXNlZCBvbiB0aGUgY291bnQgdGFibGUgbnVtYmVyCnJvd25hbWVzKGNvbWJpbmVkX2NvdW50X3RhYmxlKSA8LSBwYXN0ZTAoIlNiaiIsIHJlcCgxOjUwLCBlYWNoID0gbnJvdyhjb3VudF90YWJsZXNbWzFdXSkpLCAiX1RpbWUiLCAxOjEwKQoKYGBgCgoKX19DcmVhdGUgRmFrZSBNZXRhZGF0YV9fICAKMS4gU2V4IChNIG9yIEYsIDUwLzUwIFJhdGlvKQoyLiBBZ2UgLSBzYW1wbGUgZnJvbSBiZXR3ZWVuIDE4IGFuZCA0NQozLiBCTUkgLSBzYW1wbGUgYmV0d2VlbiAxOCBhbmQgMzUKCk1ha2UgTWV0YWRhdGEgYW5kIG1lcmdlIHdpdGggdGhlIGNvdW50IGRhdGEKYGBge3J9CiMgRGYgMSBpcyBNZXRhZGF0YQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwptZXRhX2RhdGEgPC0gIGV4cGFuZC5ncmlkKFRpbWUgPSAxOjEwLElEID0gMTo1MCkKcm93bmFtZXMobWV0YV9kYXRhKSA8LSByb3duYW1lcyhjb21iaW5lZF9jb3VudF90YWJsZSkKIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKbWV0YV9kYXRhJFNleCA8LSByZXAoYygwLCAxKSwgZWFjaCA9IDUwKQojIFNldCBzZWVkCnNldC5zZWVkKDEyMzQ1KQptZXRhX2RhdGEkQWdlIDwtIHJlcChzYW1wbGUoMTg6NDUsIDUwLCByZXBsYWNlID0gVFJVRSksIGVhY2ggPSAxMCkKIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKbWV0YV9kYXRhJEJNSSA8LSByZXAoc2FtcGxlKDE4OjM1LCA1MCwgcmVwbGFjZSA9IFRSVUUpLCBlYWNoID0gMTApCgojIENlbnRlciB0aGUgY29udGludW91cyB2YXJpYWJsZXMKbWV0YV9kYXRhJEFnZSA8LSBtZXRhX2RhdGEkQWdlIC0gbWVhbihtZXRhX2RhdGEkQWdlKQptZXRhX2RhdGEkQk1JIDwtIG1ldGFfZGF0YSRCTUkgLSBtZWFuKG1ldGFfZGF0YSRCTUkpCgoKIyBEZiAyIGlzIE1ldGFkYXRhIG1lcmdlZCB3aXRoIENvdW50cwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojUm91bmQgb2ZmIGFuZCBpbmNyZWFzZQpjb21iaW5lZF9jb3VudF90YWJsZSA8LSBhcy5kYXRhLmZyYW1lKGNvbWJpbmVkX2NvdW50X3RhYmxlICsgYWJzKG1pbihjb21iaW5lZF9jb3VudF90YWJsZSkpKQpjb21iaW5lZF9jb3VudF90YWJsZSA8LSAoY29tYmluZWRfY291bnRfdGFibGUpKjEwCm1ldGFfY291bnRzIDwtIGJhc2U6Om1lcmdlKG1ldGFfZGF0YSwgY29tYmluZWRfY291bnRfdGFibGUsIGJ5ID0icm93Lm5hbWVzIiwgYWxsID0gVFJVRSkKbWV0YV9jb3VudHMgPC0gY29sdW1uX3RvX3Jvd25hbWVzKG1ldGFfY291bnRzLCAiUm93Lm5hbWVzIikKCgpgYGAKCgpBZGQgaW4gYmlvbG9naWNhbCBjb3ZhcmlhdGVzCmBgYHtyfQojIFNldCBzZWVkCnNldC5zZWVkKDEyMzQ1KQojIEFkZGluIGNvdmFyaWF0ZXMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIFNldCB1cCBuZXcgZGF0YWZyYW1lCkxvbmdfZGF0YV9uZXcgPC0gbWV0YV9jb3VudHMKCgojIExvb3AgcnVubmluZyB0aGUgTE0gdG8gZ2V0IG5ldyB2YXJpYWJsZXMgd2l0aCBlcnJvciB0aGF0IGhhcyBhIHJhbmdlIG9mIHZhbHVlcwojIFRheGEgMjEgLSAzMCB3aWxsIGhhdmUgU2V4IGVmZmVjdApmb3IgKGkgaW4gMjY6MzUpIHsKICBlcnJvciA8LSBybm9ybShucm93KExvbmdfZGF0YV9uZXcpLCBtZWFuID0gMSwgc2QgPSAwLjYpCiAgTG9uZ19kYXRhX25ld1ssIGldIDwtIExvbmdfZGF0YV9uZXdbLCBpXSArIDAuMSAqIExvbmdfZGF0YV9uZXckU2V4ICsgZXJyb3IKfQoKIyByb3VuZCB0aGUgY291bnRzIHRvIGJyaW5nIHRoZW0gYmFjayB1cCB0byAwCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgQWRkIHRoZSBtaW5pbXVtIHZhbHVlIHRvIGJyaW5nIGV2ZXJ5dGhpbmcgdXAgdG8gYXQgbGVhc3QgMApjb3VudF90YWJsZTEgPC0gTG9uZ19kYXRhX25ld1ssNjo1NV0KCgojIHNjYWxlIHRvIHBvc2l0aXZlIGFuZCBtYWtlIGxhcmdlcgpjb3VudF90YWJsZTEgPC0gY291bnRfdGFibGUxICsgYWJzKG1pbihjb3VudF90YWJsZTEpKQpjb3VudF90YWJsZTEgPC0gcm91bmQoY291bnRfdGFibGUxKjEwKQoKI2NoYW5nZSBMb25nX2RhdGFfbmV3CkxvbmdfZGF0YV9uZXdbLDY6NTVdIDwtIGNvdW50X3RhYmxlMQpgYGAKCgoKTm93IEFkZCBpbiAwcwpgYGB7cn0KIyBTZXQgdXAgbmV3IGRhdGFmcmFtZQpwcmVkYXRhXzAgPC0gY291bnRfdGFibGUxCgojIEFkZCB0aGUgMHMgYmFjayBpbgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgoKIyBTdGVwIDE6IENhbGN1bGF0ZSB0b3RhbCBjb3VudHMgZm9yIGVhY2ggY29sdW1uCnRvdGFsX2NvdW50cyA8LSBjb2xTdW1zKHByZWRhdGFfMCkKCgojIFN0ZXAgMjogQ3JlYXRlIHByb2JhYmlsaXR5IGdyYWRpZW50CmdyYWRpZW50IDwtIHNlcSgwLjUsIDAuMiwgbGVuZ3RoLm91dCA9IG5jb2wocHJlZGF0YV8wKSkKCiMgU3RlcCAzOiBNYWtlIHRoZSBwcm9iYWJpbGl0eSBncmFkaWVudCBpbnZlcnNlIHRvIHRvdGFsIGNvdW50cyAoaWUgaGlnaGVyIHRvdGFsIHZhbHVlLCBsb3dlciBwcm9wb3J0aW9uIG9mIDBzKQp0b3RhbF9jb3VudHMgPC0gdG90YWxfY291bnRzW29yZGVyKHRvdGFsX2NvdW50cyldCmdyYWRpZW50IDwtIGdyYWRpZW50W29yZGVyKC1ncmFkaWVudCldCgojIFN0ZXAgNCAmIDU6IEdlbmVyYXRlIHJhbmRvbSBudW1iZXJzIGFuZCBzZXQgY291bnRzIHRvIDAgYmFzZWQgb24gcHJvYmFiaWxpdHkgZ3JhZGllbnQKCmZvciAoaSBpbiBzZXFfYWxvbmcodG90YWxfY291bnRzKSkgewogIHByb2IgPC0gZ3JhZGllbnRbaV0KICAjIENhbGN1bGF0ZSBudW1iZXIgb2YgMHMgdG8gYWRkIGJhc2VkIG9uIHByb2JhYmlsaXR5CiAgbnVtX3plcm9zIDwtIHN1bShydW5pZihucm93KHByZWRhdGFfMCkpIDw9IHByb2IpCiAgIyBSYW5kb21seSBzZWxlY3Qgcm93cyB0byBzZXQgdG8gMAogICMgU2V0IHRoZSBzZWVkIGZvciBlYWNoIHN1YmplY3QKICBzZXQuc2VlZCgxMjM0NSArIGkpICAKICByb3dzX3RvX3plcm8gPC0gc2FtcGxlKG5yb3cocHJlZGF0YV8wKSwgbnVtX3plcm9zKQogICMgU2V0IGNvdW50cyB0byAwCiAgcHJlZGF0YV8wW3Jvd3NfdG9femVybywgaV0gPC0gMAp9CgojIG1lcmdlIHdpdGggbWV0YWRhdGEgZm9yIHBsb3R0aW5nCnplcm9fZGF0YTEgPC0gbWVyZ2UobWV0YV9kYXRhLCBwcmVkYXRhXzAsIGJ5ID0gMCkKemVyb19kYXRhMSA8LSBjb2x1bW5fdG9fcm93bmFtZXMoemVyb19kYXRhMSwgIlJvdy5uYW1lcyIpCiNyb3VuZCB0aGUgY291bnRzCnplcm9fZGF0YTFbLDY6NTVdIDwtIHJvdW5kKHplcm9fZGF0YTFbLDY6NTVdKQpgYGAKCkdyYXBocyB0byBDaGVjawpgYGB7cn0KIyBJbmRpdmlkdWFsIFNwZWNpZXMgUGxvdHMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBQaXZvdCB0byBsb25nIGRhdGEKY291bnRfbG9uZyA8LSB0aWR5cjo6cGl2b3RfbG9uZ2VyKHplcm9fZGF0YTEsIGNvbHMgPSBzdGFydHNfd2l0aCgic3AiKSwgbmFtZXNfdG8gPSAiU3BlY2llcyIpCgojIFBsb3QgdGhlIGRhdGEKY291bnRfbG9uZyAlPiUKICBnZ3Bsb3QoYWVzKHggPSBUaW1lLCB5ID0gdmFsdWUsIGNvbG91ciA9IGFzLmZhY3RvcihJRCksCiAgICAgICAgICAgICBncm91cCA9IGFzLmZhY3RvcihJRCksIGxpbmV0eXBlID0gYXMuZmFjdG9yKElEKSkpICsKICBnZW9tX2xpbmUoKSArIAogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9qaXR0ZXIoKSArCiAgeWxhYigiQ291bnQiKSArCiAgbGFicyhsaW5ldHlwZSA9ICJJRCIsIGNvbG9yID0gIklEIikgKwogIGZhY2V0X3dyYXAofiBTcGVjaWVzKSArICAjIENyZWF0ZSBhIHBhbmVsIGZvciBlYWNoIHNwZWNpZXMKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICBnZ3RpdGxlKCJUaW1lIFNlcmllcyBvZiBOPTUwLCAwcyIpCgoKIyBEaXN0cmlidXRpb24gb2YgY291bnRzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCmhpc3QoYXMubWF0cml4KHplcm9fZGF0YTFbLDY6NTVdKSwgYnJlYWtzID0gMTAwLCBtYWluID0gIkRpc3RyaWJ1dGlvbiBvZiBHTFYgRGF0YSIsIHhsYWIgPSAiQ291bnRzIikKCiMgQ29ycmVsYXRpb24gbWF0cml4CmNvcl9yYXcxIDwtIGNvcigoemVyb19kYXRhMVssNjo1NV0pLCBtZXRob2QgPSAic3BlYXJtYW4iKQpoZWF0bWFwKGNvcl9yYXcxLCBDb2x2ID0gTkEsIFJvd3YgPSBOQSwgbWFpbiA9ICJDb3JyZWxhdGlvbiBvZiAwIGluZmxhdGVkIG5vIGNvdmFyaWF0ZXMiKQpgYGAKCgpTYXZlIHRoZSBDb3VudHMKYGBge3J9CndyaXRlLmNzdihtZXRhX2NvdW50cywgaGVyZSgiRGF0YSIsIkdMVl9TaW1EYXRhIiwgIkRhdGFzZXRfNSIsIkdMVl8wLjEwLmNzdiIpKQp3cml0ZS5jc3YoTG9uZ19kYXRhX25ldywgaGVyZSgiRGF0YSIsIkdMVl9TaW1EYXRhIiwgIkRhdGFzZXRfNSIsIkdMVl9Db3ZfMC4xMC5jc3YiKSkKd3JpdGUuY3N2KHplcm9fZGF0YTEsIGhlcmUoIkRhdGEiLCJHTFZfU2ltRGF0YSIsICJEYXRhc2V0XzUiLCJHTFZfQ292WmVyb18wLjEwLmNzdiIpKQpgYGAKCgoKIyA0LiBTaW11bGF0ZSBiZXRhID0gMS4wCioqKiAKCl9fU2ltdWxhdGUgQ291bnRzX18gIApTaW11bGF0ZSBHTFYgZm9yIDUwIGluZGl2aWR1YWxzLCA1MCBzcGVjaWVzLCAxMCB0aW1lcG9pbnRzLCBDb25uZWN0YW5jZSA9IDAuOTAsIFNleCBCZXRhID0gMS4wCmBgYHtyfQojIFNldCBzZWVkCnNldC5zZWVkKDEyMzQ1KQoKIyBTdGVwIDEgUnVuIEdMViBmb3IgbiBudW1iZXIgb2Ygc3ViamVjdCBhbmQgdGltZXBvaW50cwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIEdlbmVyYXRlIGludGVyYWN0aW9ucyBmcm9tIHVuaWZvcm0gZGlzdHJpYnV0aW9uCkFfdW5pZm9ybSA8LSByYW5kb21BKAogICAgbl9zcGVjaWVzID0gNTAsCiAgICBkaWFnb25hbCA9IC0xLjAsCiAgICBjb25uZWN0YW5jZSA9IDAuOTApCgojIENyZWF0ZSBhbiBlbXB0eSBsaXN0IHRvIHN0b3JlIHRoZSBjb3VudCB0YWJsZXMgZm9yIGVhY2ggc3ViamVjdApjb3VudF90YWJsZXMgPC0gbGlzdCgpCgoKIyBMb29wIHRocm91Z2ggNTAgc3ViamVjdHMgYW5kIGdlbmVyYXRlIGNvdW50IHRhYmxlcyBmb3IgZWFjaApmb3IgKGkgaW4gMTo1MCkgewogICMgU2V0IHRoZSBzZWVkIGZvciBlYWNoIHN1YmplY3QKICBzZXQuc2VlZCgxMjM0NSArIGkpICAKICMgR2VuZXJhbGl6ZWQgTG90a2EtVm9sdGVycmEgKGdMVikKICB0c2VfZ2x2IDwtIHNpbXVsYXRlR0xWKG5fc3BlY2llcyA9IDUwLAogICAgICAgICAgICAgICAgICAgICAgIEEgPSBBX3VuaWZvcm0sCiAgICAgICAgICAgICAgICAgICAgICAgdF9zdGFydCA9IDAsIAogICAgICAgICAgICAgICAgICAgICAgIHRfc3RvcmUgPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICBzdG9jaGFzdGljID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgbm9ybSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIGVycm9yX3ZhcmlhbmNlID0gMC4wMSkKICAKICAjIEdldCB0aGUgY291bnQgdGFibGUKICBzaW1fZGF0YSA8LSB0c2VfZ2x2QGFzc2F5c0BkYXRhQGxpc3REYXRhW1siY291bnRzIl1dCiAgCiAgIyBTdG9yZSB0aGUgY291bnQgdGFibGUgaW4gdGhlIGxpc3QKICBjb3VudF90YWJsZXNbW2ldXSA8LSB0KHNpbV9kYXRhKQp9CgojIFN0ZXAgMiAtIE1lcmdlIHRvZ2V0aGVyCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBDb21iaW5lIGFsbCBjb3VudCB0YWJsZXMgaW50byBvbmUgZGF0YSBmcmFtZQpjb21iaW5lZF9jb3VudF90YWJsZSA8LSBkby5jYWxsKHJiaW5kLCBjb3VudF90YWJsZXMpCgojIFJlbmFtZSB0aGUgcm93bmFtZXMgYmFzZWQgb24gdGhlIGNvdW50IHRhYmxlIG51bWJlcgpyb3duYW1lcyhjb21iaW5lZF9jb3VudF90YWJsZSkgPC0gcGFzdGUwKCJTYmoiLCByZXAoMTo1MCwgZWFjaCA9IG5yb3coY291bnRfdGFibGVzW1sxXV0pKSwgIl9UaW1lIiwgMToxMCkKCmBgYAoKCl9fQ3JlYXRlIEZha2UgTWV0YWRhdGFfXyAgCjEuIFNleCAoTSBvciBGLCA1MC81MCBSYXRpbykKMi4gQWdlIC0gc2FtcGxlIGZyb20gYmV0d2VlbiAxOCBhbmQgNDUKMy4gQk1JIC0gc2FtcGxlIGJldHdlZW4gMTggYW5kIDM1CgpNYWtlIE1ldGFkYXRhIGFuZCBtZXJnZSB3aXRoIHRoZSBjb3VudCBkYXRhCmBgYHtyfQojIERmIDEgaXMgTWV0YWRhdGEKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKbWV0YV9kYXRhIDwtICBleHBhbmQuZ3JpZChUaW1lID0gMToxMCxJRCA9IDE6NTApCnJvd25hbWVzKG1ldGFfZGF0YSkgPC0gcm93bmFtZXMoY29tYmluZWRfY291bnRfdGFibGUpCiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCm1ldGFfZGF0YSRTZXggPC0gcmVwKGMoMCwgMSksIGVhY2ggPSA1MCkKIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKbWV0YV9kYXRhJEFnZSA8LSByZXAoc2FtcGxlKDE4OjQ1LCA1MCwgcmVwbGFjZSA9IFRSVUUpLCBlYWNoID0gMTApCiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCm1ldGFfZGF0YSRCTUkgPC0gcmVwKHNhbXBsZSgxODozNSwgNTAsIHJlcGxhY2UgPSBUUlVFKSwgZWFjaCA9IDEwKQoKIyBDZW50ZXIgdGhlIGNvbnRpbnVvdXMgdmFyaWFibGVzCm1ldGFfZGF0YSRBZ2UgPC0gbWV0YV9kYXRhJEFnZSAtIG1lYW4obWV0YV9kYXRhJEFnZSkKbWV0YV9kYXRhJEJNSSA8LSBtZXRhX2RhdGEkQk1JIC0gbWVhbihtZXRhX2RhdGEkQk1JKQoKCiMgRGYgMiBpcyBNZXRhZGF0YSBtZXJnZWQgd2l0aCBDb3VudHMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKI1JvdW5kIG9mZiBhbmQgaW5jcmVhc2UKY29tYmluZWRfY291bnRfdGFibGUgPC0gYXMuZGF0YS5mcmFtZShjb21iaW5lZF9jb3VudF90YWJsZSArIGFicyhtaW4oY29tYmluZWRfY291bnRfdGFibGUpKSkKY29tYmluZWRfY291bnRfdGFibGUgPC0gKGNvbWJpbmVkX2NvdW50X3RhYmxlKSoxMAptZXRhX2NvdW50cyA8LSBiYXNlOjptZXJnZShtZXRhX2RhdGEsIGNvbWJpbmVkX2NvdW50X3RhYmxlLCBieSA9InJvdy5uYW1lcyIsIGFsbCA9IFRSVUUpCm1ldGFfY291bnRzIDwtIGNvbHVtbl90b19yb3duYW1lcyhtZXRhX2NvdW50cywgIlJvdy5uYW1lcyIpCgoKYGBgCgoKQWRkIGluIGJpb2xvZ2ljYWwgY292YXJpYXRlcwpgYGB7cn0KIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKIyBBZGRpbiBjb3ZhcmlhdGVzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBTZXQgdXAgbmV3IGRhdGFmcmFtZQpMb25nX2RhdGFfbmV3IDwtIG1ldGFfY291bnRzCgoKIyBMb29wIHJ1bm5pbmcgdGhlIExNIHRvIGdldCBuZXcgdmFyaWFibGVzIHdpdGggZXJyb3IgdGhhdCBoYXMgYSByYW5nZSBvZiB2YWx1ZXMKIyBUYXhhIDIxIC0gMzAgd2lsbCBoYXZlIFNleCBlZmZlY3QKZm9yIChpIGluIDI2OjM1KSB7CiAgZXJyb3IgPC0gcm5vcm0obnJvdyhMb25nX2RhdGFfbmV3KSwgbWVhbiA9IDEsIHNkID0gMC42KQogIExvbmdfZGF0YV9uZXdbLCBpXSA8LSBMb25nX2RhdGFfbmV3WywgaV0gKyAxLjAgKiBMb25nX2RhdGFfbmV3JFNleCArIGVycm9yCn0KCiMgcm91bmQgdGhlIGNvdW50cyB0byBicmluZyB0aGVtIGJhY2sgdXAgdG8gMAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIEFkZCB0aGUgbWluaW11bSB2YWx1ZSB0byBicmluZyBldmVyeXRoaW5nIHVwIHRvIGF0IGxlYXN0IDAKY291bnRfdGFibGUxIDwtIExvbmdfZGF0YV9uZXdbLDY6NTVdCgoKIyBzY2FsZSB0byBwb3NpdGl2ZSBhbmQgbWFrZSBsYXJnZXIKY291bnRfdGFibGUxIDwtIGNvdW50X3RhYmxlMSArIGFicyhtaW4oY291bnRfdGFibGUxKSkKY291bnRfdGFibGUxIDwtIHJvdW5kKGNvdW50X3RhYmxlMSoxMCkKCiNjaGFuZ2UgTG9uZ19kYXRhX25ldwpMb25nX2RhdGFfbmV3Wyw2OjU1XSA8LSBjb3VudF90YWJsZTEKYGBgCgoKCk5vdyBBZGQgaW4gMHMKYGBge3J9CiMgU2V0IHVwIG5ldyBkYXRhZnJhbWUKcHJlZGF0YV8wIDwtIGNvdW50X3RhYmxlMQoKIyBBZGQgdGhlIDBzIGJhY2sgaW4KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKCiMgU3RlcCAxOiBDYWxjdWxhdGUgdG90YWwgY291bnRzIGZvciBlYWNoIGNvbHVtbgp0b3RhbF9jb3VudHMgPC0gY29sU3VtcyhwcmVkYXRhXzApCgoKIyBTdGVwIDI6IENyZWF0ZSBwcm9iYWJpbGl0eSBncmFkaWVudApncmFkaWVudCA8LSBzZXEoMC41LCAwLjIsIGxlbmd0aC5vdXQgPSBuY29sKHByZWRhdGFfMCkpCgojIFN0ZXAgMzogTWFrZSB0aGUgcHJvYmFiaWxpdHkgZ3JhZGllbnQgaW52ZXJzZSB0byB0b3RhbCBjb3VudHMgKGllIGhpZ2hlciB0b3RhbCB2YWx1ZSwgbG93ZXIgcHJvcG9ydGlvbiBvZiAwcykKdG90YWxfY291bnRzIDwtIHRvdGFsX2NvdW50c1tvcmRlcih0b3RhbF9jb3VudHMpXQpncmFkaWVudCA8LSBncmFkaWVudFtvcmRlcigtZ3JhZGllbnQpXQoKIyBTdGVwIDQgJiA1OiBHZW5lcmF0ZSByYW5kb20gbnVtYmVycyBhbmQgc2V0IGNvdW50cyB0byAwIGJhc2VkIG9uIHByb2JhYmlsaXR5IGdyYWRpZW50Cgpmb3IgKGkgaW4gc2VxX2Fsb25nKHRvdGFsX2NvdW50cykpIHsKICBwcm9iIDwtIGdyYWRpZW50W2ldCiAgIyBDYWxjdWxhdGUgbnVtYmVyIG9mIDBzIHRvIGFkZCBiYXNlZCBvbiBwcm9iYWJpbGl0eQogIG51bV96ZXJvcyA8LSBzdW0ocnVuaWYobnJvdyhwcmVkYXRhXzApKSA8PSBwcm9iKQogICMgUmFuZG9tbHkgc2VsZWN0IHJvd3MgdG8gc2V0IHRvIDAKICAjIFNldCB0aGUgc2VlZCBmb3IgZWFjaCBzdWJqZWN0CiAgc2V0LnNlZWQoMTIzNDUgKyBpKSAgCiAgcm93c190b196ZXJvIDwtIHNhbXBsZShucm93KHByZWRhdGFfMCksIG51bV96ZXJvcykKICAjIFNldCBjb3VudHMgdG8gMAogIHByZWRhdGFfMFtyb3dzX3RvX3plcm8sIGldIDwtIDAKfQoKIyBtZXJnZSB3aXRoIG1ldGFkYXRhIGZvciBwbG90dGluZwp6ZXJvX2RhdGExIDwtIG1lcmdlKG1ldGFfZGF0YSwgcHJlZGF0YV8wLCBieSA9IDApCnplcm9fZGF0YTEgPC0gY29sdW1uX3RvX3Jvd25hbWVzKHplcm9fZGF0YTEsICJSb3cubmFtZXMiKQojcm91bmQgdGhlIGNvdW50cwp6ZXJvX2RhdGExWyw2OjU1XSA8LSByb3VuZCh6ZXJvX2RhdGExWyw2OjU1XSkKYGBgCgpHcmFwaHMgdG8gQ2hlY2sKYGBge3J9CiMgSW5kaXZpZHVhbCBTcGVjaWVzIFBsb3RzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgUGl2b3QgdG8gbG9uZyBkYXRhCmNvdW50X2xvbmcgPC0gdGlkeXI6OnBpdm90X2xvbmdlcih6ZXJvX2RhdGExLCBjb2xzID0gc3RhcnRzX3dpdGgoInNwIiksIG5hbWVzX3RvID0gIlNwZWNpZXMiKQoKIyBQbG90IHRoZSBkYXRhCmNvdW50X2xvbmcgJT4lCiAgZ2dwbG90KGFlcyh4ID0gVGltZSwgeSA9IHZhbHVlLCBjb2xvdXIgPSBhcy5mYWN0b3IoSUQpLAogICAgICAgICAgICAgZ3JvdXAgPSBhcy5mYWN0b3IoSUQpLCBsaW5ldHlwZSA9IGFzLmZhY3RvcihJRCkpKSArCiAgZ2VvbV9saW5lKCkgKyAKICBnZW9tX3BvaW50KCkgKwogIGdlb21faml0dGVyKCkgKwogIHlsYWIoIkNvdW50IikgKwogIGxhYnMobGluZXR5cGUgPSAiSUQiLCBjb2xvciA9ICJJRCIpICsKICBmYWNldF93cmFwKH4gU3BlY2llcykgKyAgIyBDcmVhdGUgYSBwYW5lbCBmb3IgZWFjaCBzcGVjaWVzCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgZ2d0aXRsZSgiVGltZSBTZXJpZXMgb2YgTj01MCwgMHMiKQoKCiMgRGlzdHJpYnV0aW9uIG9mIGNvdW50cwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpoaXN0KGFzLm1hdHJpeCh6ZXJvX2RhdGExWyw2OjU1XSksIGJyZWFrcyA9IDEwMCwgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgR0xWIERhdGEiLCB4bGFiID0gIkNvdW50cyIpCgojIENvcnJlbGF0aW9uIG1hdHJpeApjb3JfcmF3MSA8LSBjb3IoKHplcm9fZGF0YTFbLDY6NTVdKSwgbWV0aG9kID0gInNwZWFybWFuIikKaGVhdG1hcChjb3JfcmF3MSwgQ29sdiA9IE5BLCBSb3d2ID0gTkEsIG1haW4gPSAiQ29ycmVsYXRpb24gb2YgMCBpbmZsYXRlZCBubyBjb3ZhcmlhdGVzIikKYGBgCgoKU2F2ZSB0aGUgQ291bnRzCmBgYHtyfQp3cml0ZS5jc3YobWV0YV9jb3VudHMsIGhlcmUoIkRhdGEiLCJHTFZfU2ltRGF0YSIsICJEYXRhc2V0XzUiLCJHTFZfMS4wLmNzdiIpKQp3cml0ZS5jc3YoTG9uZ19kYXRhX25ldywgaGVyZSgiRGF0YSIsIkdMVl9TaW1EYXRhIiwgIkRhdGFzZXRfNSIsIkdMVl9Db3ZfMS4wLmNzdiIpKQp3cml0ZS5jc3YoemVyb19kYXRhMSwgaGVyZSgiRGF0YSIsIkdMVl9TaW1EYXRhIiwgIkRhdGFzZXRfNSIsIkdMVl9Db3ZaZXJvXzEuMC5jc3YiKSkKYGBgCgoKCiMgNS4gU2ltdWxhdGUgYmV0YSA9IDguMAoqKiogCgpfX1NpbXVsYXRlIENvdW50c19fICAKU2ltdWxhdGUgR0xWIGZvciA1MCBpbmRpdmlkdWFscywgNTAgc3BlY2llcywgMTAgdGltZXBvaW50cywgQ29ubmVjdGFuY2UgPSAwLjkwLCBTZXggQmV0YSA9IDguMApgYGB7cn0KIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKCiMgU3RlcCAxIFJ1biBHTFYgZm9yIG4gbnVtYmVyIG9mIHN1YmplY3QgYW5kIHRpbWVwb2ludHMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBHZW5lcmF0ZSBpbnRlcmFjdGlvbnMgZnJvbSB1bmlmb3JtIGRpc3RyaWJ1dGlvbgpBX3VuaWZvcm0gPC0gcmFuZG9tQSgKICAgIG5fc3BlY2llcyA9IDUwLAogICAgZGlhZ29uYWwgPSAtMS4wLAogICAgY29ubmVjdGFuY2UgPSAwLjkwKQoKIyBDcmVhdGUgYW4gZW1wdHkgbGlzdCB0byBzdG9yZSB0aGUgY291bnQgdGFibGVzIGZvciBlYWNoIHN1YmplY3QKY291bnRfdGFibGVzIDwtIGxpc3QoKQoKCiMgTG9vcCB0aHJvdWdoIDUwIHN1YmplY3RzIGFuZCBnZW5lcmF0ZSBjb3VudCB0YWJsZXMgZm9yIGVhY2gKZm9yIChpIGluIDE6NTApIHsKICAjIFNldCB0aGUgc2VlZCBmb3IgZWFjaCBzdWJqZWN0CiAgc2V0LnNlZWQoMTIzNDUgKyBpKSAgCiAjIEdlbmVyYWxpemVkIExvdGthLVZvbHRlcnJhIChnTFYpCiAgdHNlX2dsdiA8LSBzaW11bGF0ZUdMVihuX3NwZWNpZXMgPSA1MCwKICAgICAgICAgICAgICAgICAgICAgICBBID0gQV91bmlmb3JtLAogICAgICAgICAgICAgICAgICAgICAgIHRfc3RhcnQgPSAwLCAKICAgICAgICAgICAgICAgICAgICAgICB0X3N0b3JlID0gMTAsCiAgICAgICAgICAgICAgICAgICAgICAgc3RvY2hhc3RpYyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIG5vcm0gPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBlcnJvcl92YXJpYW5jZSA9IDAuMDEpCiAgCiAgIyBHZXQgdGhlIGNvdW50IHRhYmxlCiAgc2ltX2RhdGEgPC0gdHNlX2dsdkBhc3NheXNAZGF0YUBsaXN0RGF0YVtbImNvdW50cyJdXQogIAogICMgU3RvcmUgdGhlIGNvdW50IHRhYmxlIGluIHRoZSBsaXN0CiAgY291bnRfdGFibGVzW1tpXV0gPC0gdChzaW1fZGF0YSkKfQoKIyBTdGVwIDIgLSBNZXJnZSB0b2dldGhlcgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgQ29tYmluZSBhbGwgY291bnQgdGFibGVzIGludG8gb25lIGRhdGEgZnJhbWUKY29tYmluZWRfY291bnRfdGFibGUgPC0gZG8uY2FsbChyYmluZCwgY291bnRfdGFibGVzKQoKIyBSZW5hbWUgdGhlIHJvd25hbWVzIGJhc2VkIG9uIHRoZSBjb3VudCB0YWJsZSBudW1iZXIKcm93bmFtZXMoY29tYmluZWRfY291bnRfdGFibGUpIDwtIHBhc3RlMCgiU2JqIiwgcmVwKDE6NTAsIGVhY2ggPSBucm93KGNvdW50X3RhYmxlc1tbMV1dKSksICJfVGltZSIsIDE6MTApCgpgYGAKCgpfX0NyZWF0ZSBGYWtlIE1ldGFkYXRhX18gIAoxLiBTZXggKE0gb3IgRiwgNTAvNTAgUmF0aW8pCjIuIEFnZSAtIHNhbXBsZSBmcm9tIGJldHdlZW4gMTggYW5kIDQ1CjMuIEJNSSAtIHNhbXBsZSBiZXR3ZWVuIDE4IGFuZCAzNQoKTWFrZSBNZXRhZGF0YSBhbmQgbWVyZ2Ugd2l0aCB0aGUgY291bnQgZGF0YQpgYGB7cn0KIyBEZiAxIGlzIE1ldGFkYXRhCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCm1ldGFfZGF0YSA8LSAgZXhwYW5kLmdyaWQoVGltZSA9IDE6MTAsSUQgPSAxOjUwKQpyb3duYW1lcyhtZXRhX2RhdGEpIDwtIHJvd25hbWVzKGNvbWJpbmVkX2NvdW50X3RhYmxlKQojIFNldCBzZWVkCnNldC5zZWVkKDEyMzQ1KQptZXRhX2RhdGEkU2V4IDwtIHJlcChjKDAsIDEpLCBlYWNoID0gNTApCiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCm1ldGFfZGF0YSRBZ2UgPC0gcmVwKHNhbXBsZSgxODo0NSwgNTAsIHJlcGxhY2UgPSBUUlVFKSwgZWFjaCA9IDEwKQojIFNldCBzZWVkCnNldC5zZWVkKDEyMzQ1KQptZXRhX2RhdGEkQk1JIDwtIHJlcChzYW1wbGUoMTg6MzUsIDUwLCByZXBsYWNlID0gVFJVRSksIGVhY2ggPSAxMCkKCiMgQ2VudGVyIHRoZSBjb250aW51b3VzIHZhcmlhYmxlcwptZXRhX2RhdGEkQWdlIDwtIG1ldGFfZGF0YSRBZ2UgLSBtZWFuKG1ldGFfZGF0YSRBZ2UpCm1ldGFfZGF0YSRCTUkgPC0gbWV0YV9kYXRhJEJNSSAtIG1lYW4obWV0YV9kYXRhJEJNSSkKCgojIERmIDIgaXMgTWV0YWRhdGEgbWVyZ2VkIHdpdGggQ291bnRzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiNSb3VuZCBvZmYgYW5kIGluY3JlYXNlCmNvbWJpbmVkX2NvdW50X3RhYmxlIDwtIGFzLmRhdGEuZnJhbWUoY29tYmluZWRfY291bnRfdGFibGUgKyBhYnMobWluKGNvbWJpbmVkX2NvdW50X3RhYmxlKSkpCmNvbWJpbmVkX2NvdW50X3RhYmxlIDwtIChjb21iaW5lZF9jb3VudF90YWJsZSkqMTAKbWV0YV9jb3VudHMgPC0gYmFzZTo6bWVyZ2UobWV0YV9kYXRhLCBjb21iaW5lZF9jb3VudF90YWJsZSwgYnkgPSJyb3cubmFtZXMiLCBhbGwgPSBUUlVFKQptZXRhX2NvdW50cyA8LSBjb2x1bW5fdG9fcm93bmFtZXMobWV0YV9jb3VudHMsICJSb3cubmFtZXMiKQoKCmBgYAoKCkFkZCBpbiBiaW9sb2dpY2FsIGNvdmFyaWF0ZXMKYGBge3J9CiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCiMgQWRkaW4gY292YXJpYXRlcwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgU2V0IHVwIG5ldyBkYXRhZnJhbWUKTG9uZ19kYXRhX25ldyA8LSBtZXRhX2NvdW50cwoKCiMgTG9vcCBydW5uaW5nIHRoZSBMTSB0byBnZXQgbmV3IHZhcmlhYmxlcyB3aXRoIGVycm9yIHRoYXQgaGFzIGEgcmFuZ2Ugb2YgdmFsdWVzCgojIFRheGEgMjEgLSAzMCB3aWxsIGhhdmUgU2V4IGVmZmVjdApmb3IgKGkgaW4gMjY6MzUpIHsKICBlcnJvciA8LSBybm9ybShucm93KExvbmdfZGF0YV9uZXcpLCBtZWFuID0gMSwgc2QgPSAwLjYpCiAgTG9uZ19kYXRhX25ld1ssIGldIDwtIExvbmdfZGF0YV9uZXdbLCBpXSArIDguMCAqIExvbmdfZGF0YV9uZXckU2V4ICsgZXJyb3IKfQoKCiMgcm91bmQgdGhlIGNvdW50cyB0byBicmluZyB0aGVtIGJhY2sgdXAgdG8gMAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIEFkZCB0aGUgbWluaW11bSB2YWx1ZSB0byBicmluZyBldmVyeXRoaW5nIHVwIHRvIGF0IGxlYXN0IDAKY291bnRfdGFibGUxIDwtIExvbmdfZGF0YV9uZXdbLDY6NTVdCgoKIyBzY2FsZSB0byBwb3NpdGl2ZSBhbmQgbWFrZSBsYXJnZXIKY291bnRfdGFibGUxIDwtIGNvdW50X3RhYmxlMSArIGFicyhtaW4oY291bnRfdGFibGUxKSkKY291bnRfdGFibGUxIDwtIHJvdW5kKGNvdW50X3RhYmxlMSoxMCkKCiNjaGFuZ2UgTG9uZ19kYXRhX25ldwpMb25nX2RhdGFfbmV3Wyw2OjU1XSA8LSBjb3VudF90YWJsZTEKYGBgCgoKCk5vdyBBZGQgaW4gMHMKYGBge3J9CiMgU2V0IHVwIG5ldyBkYXRhZnJhbWUKcHJlZGF0YV8wIDwtIGNvdW50X3RhYmxlMQoKIyBBZGQgdGhlIDBzIGJhY2sgaW4KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKCiMgU3RlcCAxOiBDYWxjdWxhdGUgdG90YWwgY291bnRzIGZvciBlYWNoIGNvbHVtbgp0b3RhbF9jb3VudHMgPC0gY29sU3VtcyhwcmVkYXRhXzApCgoKIyBTdGVwIDI6IENyZWF0ZSBwcm9iYWJpbGl0eSBncmFkaWVudApncmFkaWVudCA8LSBzZXEoMC41LCAwLjIsIGxlbmd0aC5vdXQgPSBuY29sKHByZWRhdGFfMCkpCgojIFN0ZXAgMzogTWFrZSB0aGUgcHJvYmFiaWxpdHkgZ3JhZGllbnQgaW52ZXJzZSB0byB0b3RhbCBjb3VudHMgKGllIGhpZ2hlciB0b3RhbCB2YWx1ZSwgbG93ZXIgcHJvcG9ydGlvbiBvZiAwcykKdG90YWxfY291bnRzIDwtIHRvdGFsX2NvdW50c1tvcmRlcih0b3RhbF9jb3VudHMpXQpncmFkaWVudCA8LSBncmFkaWVudFtvcmRlcigtZ3JhZGllbnQpXQoKIyBTdGVwIDQgJiA1OiBHZW5lcmF0ZSByYW5kb20gbnVtYmVycyBhbmQgc2V0IGNvdW50cyB0byAwIGJhc2VkIG9uIHByb2JhYmlsaXR5IGdyYWRpZW50Cgpmb3IgKGkgaW4gc2VxX2Fsb25nKHRvdGFsX2NvdW50cykpIHsKICBwcm9iIDwtIGdyYWRpZW50W2ldCiAgIyBDYWxjdWxhdGUgbnVtYmVyIG9mIDBzIHRvIGFkZCBiYXNlZCBvbiBwcm9iYWJpbGl0eQogIG51bV96ZXJvcyA8LSBzdW0ocnVuaWYobnJvdyhwcmVkYXRhXzApKSA8PSBwcm9iKQogICMgUmFuZG9tbHkgc2VsZWN0IHJvd3MgdG8gc2V0IHRvIDAKICAjIFNldCB0aGUgc2VlZCBmb3IgZWFjaCBzdWJqZWN0CiAgc2V0LnNlZWQoMTIzNDUgKyBpKSAgCiAgcm93c190b196ZXJvIDwtIHNhbXBsZShucm93KHByZWRhdGFfMCksIG51bV96ZXJvcykKICAjIFNldCBjb3VudHMgdG8gMAogIHByZWRhdGFfMFtyb3dzX3RvX3plcm8sIGldIDwtIDAKfQoKIyBtZXJnZSB3aXRoIG1ldGFkYXRhIGZvciBwbG90dGluZwp6ZXJvX2RhdGExIDwtIG1lcmdlKG1ldGFfZGF0YSwgcHJlZGF0YV8wLCBieSA9IDApCnplcm9fZGF0YTEgPC0gY29sdW1uX3RvX3Jvd25hbWVzKHplcm9fZGF0YTEsICJSb3cubmFtZXMiKQojcm91bmQgdGhlIGNvdW50cwp6ZXJvX2RhdGExWyw2OjU1XSA8LSByb3VuZCh6ZXJvX2RhdGExWyw2OjU1XSkKYGBgCgpHcmFwaHMgdG8gQ2hlY2sKYGBge3J9CiMgSW5kaXZpZHVhbCBTcGVjaWVzIFBsb3RzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgUGl2b3QgdG8gbG9uZyBkYXRhCmNvdW50X2xvbmcgPC0gdGlkeXI6OnBpdm90X2xvbmdlcih6ZXJvX2RhdGExLCBjb2xzID0gc3RhcnRzX3dpdGgoInNwIiksIG5hbWVzX3RvID0gIlNwZWNpZXMiKQoKIyBQbG90IHRoZSBkYXRhCmNvdW50X2xvbmcgJT4lCiAgZ2dwbG90KGFlcyh4ID0gVGltZSwgeSA9IHZhbHVlLCBjb2xvdXIgPSBhcy5mYWN0b3IoSUQpLAogICAgICAgICAgICAgZ3JvdXAgPSBhcy5mYWN0b3IoSUQpLCBsaW5ldHlwZSA9IGFzLmZhY3RvcihJRCkpKSArCiAgZ2VvbV9saW5lKCkgKyAKICBnZW9tX3BvaW50KCkgKwogIGdlb21faml0dGVyKCkgKwogIHlsYWIoIkNvdW50IikgKwogIGxhYnMobGluZXR5cGUgPSAiSUQiLCBjb2xvciA9ICJJRCIpICsKICBmYWNldF93cmFwKH4gU3BlY2llcykgKyAgIyBDcmVhdGUgYSBwYW5lbCBmb3IgZWFjaCBzcGVjaWVzCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgZ2d0aXRsZSgiVGltZSBTZXJpZXMgb2YgTj01MCwgMHMiKQoKCiMgRGlzdHJpYnV0aW9uIG9mIGNvdW50cwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpoaXN0KGFzLm1hdHJpeCh6ZXJvX2RhdGExWyw2OjU1XSksIGJyZWFrcyA9IDEwMCwgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgR0xWIERhdGEiLCB4bGFiID0gIkNvdW50cyIpCgojIENvcnJlbGF0aW9uIG1hdHJpeApjb3JfcmF3MSA8LSBjb3IoKHplcm9fZGF0YTFbLDY6NTVdKSwgbWV0aG9kID0gInNwZWFybWFuIikKaGVhdG1hcChjb3JfcmF3MSwgQ29sdiA9IE5BLCBSb3d2ID0gTkEsIG1haW4gPSAiQ29ycmVsYXRpb24gb2YgMCBpbmZsYXRlZCBubyBjb3ZhcmlhdGVzIikKYGBgCgoKU2F2ZSB0aGUgQ291bnRzCmBgYHtyfQp3cml0ZS5jc3YobWV0YV9jb3VudHMsIGhlcmUoIkRhdGEiLCJHTFZfU2ltRGF0YSIsICJEYXRhc2V0XzUiLCJHTFZfOC4wLmNzdiIpKQp3cml0ZS5jc3YoTG9uZ19kYXRhX25ldywgaGVyZSgiRGF0YSIsIkdMVl9TaW1EYXRhIiwgIkRhdGFzZXRfNSIsIkdMVl9Db3ZfOC4wLmNzdiIpKQp3cml0ZS5jc3YoemVyb19kYXRhMSwgaGVyZSgiRGF0YSIsIkdMVl9TaW1EYXRhIiwgIkRhdGFzZXRfNSIsIkdMVl9Db3ZaZXJvXzguMC5jc3YiKSkKYGBgCgoKCgojIDYuIFNpbXVsYXRlIGJldGEgPSAxNS4wCioqKiAKCl9fU2ltdWxhdGUgQ291bnRzX18gIApTaW11bGF0ZSBHTFYgZm9yIDUwIGluZGl2aWR1YWxzLCA1MCBzcGVjaWVzLCAxMCB0aW1lcG9pbnRzLCBDb25uZWN0YW5jZSA9IDAuOTAsIFNleCBCZXRhID0gMTUuMApgYGB7cn0KIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKCiMgU3RlcCAxIFJ1biBHTFYgZm9yIG4gbnVtYmVyIG9mIHN1YmplY3QgYW5kIHRpbWVwb2ludHMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBHZW5lcmF0ZSBpbnRlcmFjdGlvbnMgZnJvbSB1bmlmb3JtIGRpc3RyaWJ1dGlvbgpBX3VuaWZvcm0gPC0gcmFuZG9tQSgKICAgIG5fc3BlY2llcyA9IDUwLAogICAgZGlhZ29uYWwgPSAtMS4wLAogICAgY29ubmVjdGFuY2UgPSAwLjkwKQoKIyBDcmVhdGUgYW4gZW1wdHkgbGlzdCB0byBzdG9yZSB0aGUgY291bnQgdGFibGVzIGZvciBlYWNoIHN1YmplY3QKY291bnRfdGFibGVzIDwtIGxpc3QoKQoKCiMgTG9vcCB0aHJvdWdoIDUwIHN1YmplY3RzIGFuZCBnZW5lcmF0ZSBjb3VudCB0YWJsZXMgZm9yIGVhY2gKZm9yIChpIGluIDE6NTApIHsKICAjIFNldCB0aGUgc2VlZCBmb3IgZWFjaCBzdWJqZWN0CiAgc2V0LnNlZWQoMTIzNDUgKyBpKSAgCiAjIEdlbmVyYWxpemVkIExvdGthLVZvbHRlcnJhIChnTFYpCiAgdHNlX2dsdiA8LSBzaW11bGF0ZUdMVihuX3NwZWNpZXMgPSA1MCwKICAgICAgICAgICAgICAgICAgICAgICBBID0gQV91bmlmb3JtLAogICAgICAgICAgICAgICAgICAgICAgIHRfc3RhcnQgPSAwLCAKICAgICAgICAgICAgICAgICAgICAgICB0X3N0b3JlID0gMTAsCiAgICAgICAgICAgICAgICAgICAgICAgc3RvY2hhc3RpYyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIG5vcm0gPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBlcnJvcl92YXJpYW5jZSA9IDAuMDEpCiAgCiAgIyBHZXQgdGhlIGNvdW50IHRhYmxlCiAgc2ltX2RhdGEgPC0gdHNlX2dsdkBhc3NheXNAZGF0YUBsaXN0RGF0YVtbImNvdW50cyJdXQogIAogICMgU3RvcmUgdGhlIGNvdW50IHRhYmxlIGluIHRoZSBsaXN0CiAgY291bnRfdGFibGVzW1tpXV0gPC0gdChzaW1fZGF0YSkKfQoKIyBTdGVwIDIgLSBNZXJnZSB0b2dldGhlcgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgQ29tYmluZSBhbGwgY291bnQgdGFibGVzIGludG8gb25lIGRhdGEgZnJhbWUKY29tYmluZWRfY291bnRfdGFibGUgPC0gZG8uY2FsbChyYmluZCwgY291bnRfdGFibGVzKQoKIyBSZW5hbWUgdGhlIHJvd25hbWVzIGJhc2VkIG9uIHRoZSBjb3VudCB0YWJsZSBudW1iZXIKcm93bmFtZXMoY29tYmluZWRfY291bnRfdGFibGUpIDwtIHBhc3RlMCgiU2JqIiwgcmVwKDE6NTAsIGVhY2ggPSBucm93KGNvdW50X3RhYmxlc1tbMV1dKSksICJfVGltZSIsIDE6MTApCgpgYGAKCgpfX0NyZWF0ZSBGYWtlIE1ldGFkYXRhX18gIAoxLiBTZXggKE0gb3IgRiwgNTAvNTAgUmF0aW8pCjIuIEFnZSAtIHNhbXBsZSBmcm9tIGJldHdlZW4gMTggYW5kIDQ1CjMuIEJNSSAtIHNhbXBsZSBiZXR3ZWVuIDE4IGFuZCAzNQoKTWFrZSBNZXRhZGF0YSBhbmQgbWVyZ2Ugd2l0aCB0aGUgY291bnQgZGF0YQpgYGB7cn0KIyBEZiAxIGlzIE1ldGFkYXRhCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCm1ldGFfZGF0YSA8LSAgZXhwYW5kLmdyaWQoVGltZSA9IDE6MTAsSUQgPSAxOjUwKQpyb3duYW1lcyhtZXRhX2RhdGEpIDwtIHJvd25hbWVzKGNvbWJpbmVkX2NvdW50X3RhYmxlKQojIFNldCBzZWVkCnNldC5zZWVkKDEyMzQ1KQptZXRhX2RhdGEkU2V4IDwtIHJlcChjKDAsIDEpLCBlYWNoID0gNTApCiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCm1ldGFfZGF0YSRBZ2UgPC0gcmVwKHNhbXBsZSgxODo0NSwgNTAsIHJlcGxhY2UgPSBUUlVFKSwgZWFjaCA9IDEwKQojIFNldCBzZWVkCnNldC5zZWVkKDEyMzQ1KQptZXRhX2RhdGEkQk1JIDwtIHJlcChzYW1wbGUoMTg6MzUsIDUwLCByZXBsYWNlID0gVFJVRSksIGVhY2ggPSAxMCkKCiMgQ2VudGVyIHRoZSBjb250aW51b3VzIHZhcmlhYmxlcwptZXRhX2RhdGEkQWdlIDwtIG1ldGFfZGF0YSRBZ2UgLSBtZWFuKG1ldGFfZGF0YSRBZ2UpCm1ldGFfZGF0YSRCTUkgPC0gbWV0YV9kYXRhJEJNSSAtIG1lYW4obWV0YV9kYXRhJEJNSSkKCgojIERmIDIgaXMgTWV0YWRhdGEgbWVyZ2VkIHdpdGggQ291bnRzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiNSb3VuZCBvZmYgYW5kIGluY3JlYXNlCmNvbWJpbmVkX2NvdW50X3RhYmxlIDwtIGFzLmRhdGEuZnJhbWUoY29tYmluZWRfY291bnRfdGFibGUgKyBhYnMobWluKGNvbWJpbmVkX2NvdW50X3RhYmxlKSkpCmNvbWJpbmVkX2NvdW50X3RhYmxlIDwtIChjb21iaW5lZF9jb3VudF90YWJsZSkqMTAKbWV0YV9jb3VudHMgPC0gYmFzZTo6bWVyZ2UobWV0YV9kYXRhLCBjb21iaW5lZF9jb3VudF90YWJsZSwgYnkgPSJyb3cubmFtZXMiLCBhbGwgPSBUUlVFKQptZXRhX2NvdW50cyA8LSBjb2x1bW5fdG9fcm93bmFtZXMobWV0YV9jb3VudHMsICJSb3cubmFtZXMiKQoKCmBgYAoKCkFkZCBpbiBiaW9sb2dpY2FsIGNvdmFyaWF0ZXMKYGBge3J9CiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCiMgQWRkaW4gY292YXJpYXRlcwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgU2V0IHVwIG5ldyBkYXRhZnJhbWUKTG9uZ19kYXRhX25ldyA8LSBtZXRhX2NvdW50cwoKCiMgTG9vcCBydW5uaW5nIHRoZSBMTSB0byBnZXQgbmV3IHZhcmlhYmxlcyB3aXRoIGVycm9yIHRoYXQgaGFzIGEgcmFuZ2Ugb2YgdmFsdWVzCiMgVGF4YSAyMSAtIDMwIHdpbGwgaGF2ZSBTZXggZWZmZWN0CmZvciAoaSBpbiAyNjozNSkgewogIGVycm9yIDwtIHJub3JtKG5yb3coTG9uZ19kYXRhX25ldyksIG1lYW4gPSAxLCBzZCA9IDAuNikKICBMb25nX2RhdGFfbmV3WywgaV0gPC0gTG9uZ19kYXRhX25ld1ssIGldICsgMTUgKiBMb25nX2RhdGFfbmV3JFNleCArIGVycm9yCn0KCiMgcm91bmQgdGhlIGNvdW50cyB0byBicmluZyB0aGVtIGJhY2sgdXAgdG8gMAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIEFkZCB0aGUgbWluaW11bSB2YWx1ZSB0byBicmluZyBldmVyeXRoaW5nIHVwIHRvIGF0IGxlYXN0IDAKY291bnRfdGFibGUxIDwtIExvbmdfZGF0YV9uZXdbLDY6NTVdCgoKIyBzY2FsZSB0byBwb3NpdGl2ZSBhbmQgbWFrZSBsYXJnZXIKY291bnRfdGFibGUxIDwtIGNvdW50X3RhYmxlMSArIGFicyhtaW4oY291bnRfdGFibGUxKSkKY291bnRfdGFibGUxIDwtIHJvdW5kKGNvdW50X3RhYmxlMSoxMCkKCiNjaGFuZ2UgTG9uZ19kYXRhX25ldwpMb25nX2RhdGFfbmV3Wyw2OjU1XSA8LSBjb3VudF90YWJsZTEKYGBgCgoKCk5vdyBBZGQgaW4gMHMKYGBge3J9CiMgU2V0IHVwIG5ldyBkYXRhZnJhbWUKcHJlZGF0YV8wIDwtIGNvdW50X3RhYmxlMQoKIyBBZGQgdGhlIDBzIGJhY2sgaW4KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKCiMgU3RlcCAxOiBDYWxjdWxhdGUgdG90YWwgY291bnRzIGZvciBlYWNoIGNvbHVtbgp0b3RhbF9jb3VudHMgPC0gY29sU3VtcyhwcmVkYXRhXzApCgoKIyBTdGVwIDI6IENyZWF0ZSBwcm9iYWJpbGl0eSBncmFkaWVudApncmFkaWVudCA8LSBzZXEoMC41LCAwLjIsIGxlbmd0aC5vdXQgPSBuY29sKHByZWRhdGFfMCkpCgojIFN0ZXAgMzogTWFrZSB0aGUgcHJvYmFiaWxpdHkgZ3JhZGllbnQgaW52ZXJzZSB0byB0b3RhbCBjb3VudHMgKGllIGhpZ2hlciB0b3RhbCB2YWx1ZSwgbG93ZXIgcHJvcG9ydGlvbiBvZiAwcykKdG90YWxfY291bnRzIDwtIHRvdGFsX2NvdW50c1tvcmRlcih0b3RhbF9jb3VudHMpXQpncmFkaWVudCA8LSBncmFkaWVudFtvcmRlcigtZ3JhZGllbnQpXQoKIyBTdGVwIDQgJiA1OiBHZW5lcmF0ZSByYW5kb20gbnVtYmVycyBhbmQgc2V0IGNvdW50cyB0byAwIGJhc2VkIG9uIHByb2JhYmlsaXR5IGdyYWRpZW50Cgpmb3IgKGkgaW4gc2VxX2Fsb25nKHRvdGFsX2NvdW50cykpIHsKICBwcm9iIDwtIGdyYWRpZW50W2ldCiAgIyBDYWxjdWxhdGUgbnVtYmVyIG9mIDBzIHRvIGFkZCBiYXNlZCBvbiBwcm9iYWJpbGl0eQogIG51bV96ZXJvcyA8LSBzdW0ocnVuaWYobnJvdyhwcmVkYXRhXzApKSA8PSBwcm9iKQogICMgUmFuZG9tbHkgc2VsZWN0IHJvd3MgdG8gc2V0IHRvIDAKICAjIFNldCB0aGUgc2VlZCBmb3IgZWFjaCBzdWJqZWN0CiAgc2V0LnNlZWQoMTIzNDUgKyBpKSAgCiAgcm93c190b196ZXJvIDwtIHNhbXBsZShucm93KHByZWRhdGFfMCksIG51bV96ZXJvcykKICAjIFNldCBjb3VudHMgdG8gMAogIHByZWRhdGFfMFtyb3dzX3RvX3plcm8sIGldIDwtIDAKfQoKIyBtZXJnZSB3aXRoIG1ldGFkYXRhIGZvciBwbG90dGluZwp6ZXJvX2RhdGExIDwtIG1lcmdlKG1ldGFfZGF0YSwgcHJlZGF0YV8wLCBieSA9IDApCnplcm9fZGF0YTEgPC0gY29sdW1uX3RvX3Jvd25hbWVzKHplcm9fZGF0YTEsICJSb3cubmFtZXMiKQojcm91bmQgdGhlIGNvdW50cwp6ZXJvX2RhdGExWyw2OjU1XSA8LSByb3VuZCh6ZXJvX2RhdGExWyw2OjU1XSkKYGBgCgpHcmFwaHMgdG8gQ2hlY2sKYGBge3J9CiMgSW5kaXZpZHVhbCBTcGVjaWVzIFBsb3RzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgUGl2b3QgdG8gbG9uZyBkYXRhCmNvdW50X2xvbmcgPC0gdGlkeXI6OnBpdm90X2xvbmdlcih6ZXJvX2RhdGExLCBjb2xzID0gc3RhcnRzX3dpdGgoInNwIiksIG5hbWVzX3RvID0gIlNwZWNpZXMiKQoKIyBQbG90IHRoZSBkYXRhCmNvdW50X2xvbmcgJT4lCiAgZ2dwbG90KGFlcyh4ID0gVGltZSwgeSA9IHZhbHVlLCBjb2xvdXIgPSBhcy5mYWN0b3IoSUQpLAogICAgICAgICAgICAgZ3JvdXAgPSBhcy5mYWN0b3IoSUQpLCBsaW5ldHlwZSA9IGFzLmZhY3RvcihJRCkpKSArCiAgZ2VvbV9saW5lKCkgKyAKICBnZW9tX3BvaW50KCkgKwogIGdlb21faml0dGVyKCkgKwogIHlsYWIoIkNvdW50IikgKwogIGxhYnMobGluZXR5cGUgPSAiSUQiLCBjb2xvciA9ICJJRCIpICsKICBmYWNldF93cmFwKH4gU3BlY2llcykgKyAgIyBDcmVhdGUgYSBwYW5lbCBmb3IgZWFjaCBzcGVjaWVzCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgZ2d0aXRsZSgiVGltZSBTZXJpZXMgb2YgTj01MCwgMHMiKQoKCiMgRGlzdHJpYnV0aW9uIG9mIGNvdW50cwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpoaXN0KGFzLm1hdHJpeCh6ZXJvX2RhdGExWyw2OjU1XSksIGJyZWFrcyA9IDEwMCwgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgR0xWIERhdGEiLCB4bGFiID0gIkNvdW50cyIpCgojIENvcnJlbGF0aW9uIG1hdHJpeApjb3JfcmF3MSA8LSBjb3IoKHplcm9fZGF0YTFbLDY6NTVdKSwgbWV0aG9kID0gInNwZWFybWFuIikKaGVhdG1hcChjb3JfcmF3MSwgQ29sdiA9IE5BLCBSb3d2ID0gTkEsIG1haW4gPSAiQ29ycmVsYXRpb24gb2YgMCBpbmZsYXRlZCBubyBjb3ZhcmlhdGVzIikKYGBgCgoKU2F2ZSB0aGUgQ291bnRzCmBgYHtyfQp3cml0ZS5jc3YobWV0YV9jb3VudHMsIGhlcmUoIkRhdGEiLCJHTFZfU2ltRGF0YSIsICJEYXRhc2V0XzUiLCJHTFZfMTUuMC5jc3YiKSkKd3JpdGUuY3N2KExvbmdfZGF0YV9uZXcsIGhlcmUoIkRhdGEiLCJHTFZfU2ltRGF0YSIsICJEYXRhc2V0XzUiLCJHTFZfQ292XzE1LjAuY3N2IikpCndyaXRlLmNzdih6ZXJvX2RhdGExLCBoZXJlKCJEYXRhIiwiR0xWX1NpbURhdGEiLCAiRGF0YXNldF81IiwiR0xWX0Nvdlplcm9fMTUuMC5jc3YiKSkKYGBgCg==